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.

Dependencies:   mbed

Revision:
0:0826fcc5d020
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Fat/usbhost_fat.c	Wed Jan 13 01:29:30 2010 +0000
@@ -0,0 +1,1043 @@
+/*
+**************************************************************************************************************
+*                                                 NXP USB Host Stack
+*
+*                                     (c) Copyright 2008, NXP SemiConductors
+*                                     (c) Copyright 2008, OnChip  Technologies LLC
+*                                                 All Rights Reserved
+*
+*                                                  www.nxp.com
+*                                               www.onchiptech.com
+*
+* File           : usbhost_fat.c
+* Programmer(s)  : Ravikanth.P
+* Version        :
+*
+**************************************************************************************************************
+*/
+
+/*
+**************************************************************************************************************
+*                                           INCLUDE HEADER FILES
+**************************************************************************************************************
+*/
+
+#include  "usbhost_fat.h"
+
+/*
+**************************************************************************************************************
+*                                              GLOBAL VARIABLES
+**************************************************************************************************************
+*/
+
+#define MAX_FILE_DESCRIPTORS 2
+static  BOOT_SEC    FAT_BootSec;
+static  FILE_ENTRY  FAT_FileEntry[MAX_FILE_DESCRIPTORS];
+
+/*
+**************************************************************************************************************
+*                                         INITIALIZE THE FILE SYSTEM
+*
+* Description: This function initializes the FAT16 file system
+*
+* Arguments  : None
+*
+* Returns    : OK		              if Success
+*              ERR_INVALID_BOOTSIG    if Failed
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S  FAT_Init (void)
+{
+    USB_INT16U  boot_sig;
+    USB_INT32S  rc, i;
+    FILE_ENTRY	*entry;
+
+    for (i=0;i<MAX_FILE_DESCRIPTORS;i++) {
+    	entry = &FAT_FileEntry[i];
+        entry->CurrClus       = 0;
+        entry->CurrClusOffset = 0;
+        entry->FileSize       = 0;
+        entry->EntrySec       = 0;
+        entry->EntrySecOffset = 0;
+        entry->FileStatus     = 0;
+    }
+
+    MS_BulkRecv(0, 1, FATBuffer);
+    boot_sig = ReadLE16U(&FATBuffer[510]);
+    if (boot_sig != 0xAA55) {
+        rc = ERR_INVALID_BOOT_SIG;
+    } else {
+        if (FATBuffer[0] != 0xEB && FATBuffer[0] != 0xE9) {
+            FAT_BootSec.BootSecOffset = ReadLE32U(&FATBuffer[454]);
+            MS_BulkRecv(FAT_BootSec.BootSecOffset, 1, FATBuffer);
+        }
+        FAT_BootSec.BytsPerSec      = ReadLE16U(&FATBuffer[11]);          /* Bytes per cluster              */
+        FAT_BootSec.SecPerClus      = FATBuffer[13];                      /* Sectors per cluster            */
+                                                                          /* Reserved sector count          */
+        FAT_BootSec.RsvdSecCnt      = ReadLE16U(&FATBuffer[14]) + FAT_BootSec.BootSecOffset;
+        FAT_BootSec.NumFATs         = FATBuffer[16];                      /* Number of FAT copies           */
+        FAT_BootSec.RootEntCnt      = ReadLE16U(&FATBuffer[17]);          /* Root entry count               */
+        FAT_BootSec.TotSec16        = ReadLE16U(&FATBuffer[19]);          /* Total FAT16 sectors            */
+        FAT_BootSec.TotSec32        = ReadLE32U(&FATBuffer[32]);          /* Total FAT32 sectors            */
+        FAT_BootSec.FATSz16         = ReadLE16U(&FATBuffer[22]);          /* Size of the FAT table          */
+                                                                          /* Bytes per cluster              */
+        FAT_BootSec.BytsPerClus     = (FAT_BootSec.BytsPerSec * FAT_BootSec.SecPerClus);
+                                                                          /* Root directory starting sector */
+        FAT_BootSec.RootDirStartSec = FAT_BootSec.RsvdSecCnt + (FAT_BootSec.FATSz16 * FAT_BootSec.NumFATs);
+                                                                      /* Sectors occupied by root directory */
+        FAT_BootSec.RootDirSec      = ((FAT_BootSec.RootEntCnt * 32) + (FAT_BootSec.BytsPerSec - 1)) /
+                                       (FAT_BootSec.BytsPerSec);
+                                                                          /* First data sector              */
+        FAT_BootSec.FirstDataSec    = FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec;
+        FAT_BootSec.FATType         = FAT_GetFATType();                   /* Type of FAT                    */
+        if (FAT_BootSec.FATType == FAT_16) {
+            rc = OK;
+        } else {
+            rc = ERR_FAT_NOT_SUPPORTED;
+            PRINT_Err(rc);
+        }
+    }
+    return (rc);
+}
+
+/*
+**************************************************************************************************************
+*                                         GET FILE SYSTEM TYPE
+*
+* Description: This function returns the file system type with which the disk is formatted
+*
+* Arguments  : None
+*
+* Returns    : FAT16           On Success
+*              ERR_FAT_TYPE    On Failure
+*
+**************************************************************************************************************
+*/
+
+USB_INT08U  FAT_GetFATType (void)
+{
+    USB_INT08U  fat_type;
+    USB_INT32U  tot_sec;
+    USB_INT32U  tot_data_clus;
+
+
+    if (FAT_BootSec.TotSec16 != 0) {                             /* Get total sectors in the disk           */
+        tot_sec = FAT_BootSec.TotSec16;
+    } else {
+        tot_sec = FAT_BootSec.TotSec32;
+    }
+
+    tot_data_clus = tot_sec / (FAT_BootSec.SecPerClus);          /* Get total data clusters in the disk     */
+                                                                 /* If total data clusters >= 4085 and      */
+                                                                 /* < 65525, then it is FAT16 file system   */
+    if (tot_data_clus >= 4085 && tot_data_clus < 65525) {
+        fat_type = FAT_16;
+    } else {
+        fat_type = 0;
+    }
+
+    return (fat_type);
+}
+
+/*
+**************************************************************************************************************
+*                                                OPENING A FILE
+*
+* Description: This function stores the attributes of a file, such as starting cluster, file size, 
+*              sector where the file entry is stored and offset of the entry in that sector
+*
+* Arguments  : file_name    Name of the file. The file must be in root directory.
+*
+* Returns    : pointer to the entry    On Success
+*              NULL                    On Failure
+* 
+* Modifed 6/9/08 WCB returns a file descriptor which is the INDEX+1 to the entry.
+* returning the entry address itself could be interpreted as a negative number --
+* and thus an error -- for memory locations of 0x80000000 and above.  We return
+* INDEX+1 instead of just the index to avoid returning a file descriptor of zero,
+* which could be potentially confused with an error.
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S  FILE_Open (USB_INT08U  *file_name,
+                       USB_INT08U   flags)
+{
+    USB_INT32S   rc;
+    FILE_ENTRY  *entry = 0;
+    USB_INT32S  fd = -1;
+
+    do {
+    	if (FAT_FileEntry[++fd].FileStatus == 0)
+    		entry = &FAT_FileEntry[fd];
+    } while ((entry == 0) && (fd < MAX_FILE_DESCRIPTORS-1));
+    if (entry == 0) {
+        return (ERR_OPEN_LIMIT_REACHED);
+    }
+    if (flags == RDONLY) {                       /* Search for a file. If it doesn't exist, don't create it */
+        rc = FAT_FindEntry(file_name, entry);
+        if (rc == MATCH_FOUND) {
+            entry->FileStatus = 1;
+            rc = fd+1;
+        }
+    } else {                                     /* Search for a file. If it doesn't exist, create it       */
+        rc = FAT_CreateEntry(file_name, entry);
+        if (rc == MATCH_FOUND) {
+            entry->FileStatus = 1;
+            rc = fd+1;
+        }
+    }
+    return (rc);
+}
+
+/*
+**************************************************************************************************************
+*                                                 FINDING AN ENTRY
+*
+* Description: This function searches for a file name in the root directory
+*
+* Arguments  : ent_name_given    Pointer to the file name to be searched.
+*              entry             Pointer to the entry structure. The attributes of the file are stored in this
+*                                structure if the file was found in the root directory.
+*
+* Returns    : MATCH_FOUND       if the file was found in the root directory.
+*              MATCH_NOT_FOUND   if the file was not found in the root directory.
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S  FAT_FindEntry (USB_INT08U  *ent_name_given,
+                           FILE_ENTRY  *entry)
+{
+              USB_INT32U   sec_num;
+    volatile  USB_INT08U  *buf;
+              USB_INT08U   ent_type;
+              USB_INT08U   ent_name_read[13];
+
+
+    for (sec_num = FAT_BootSec.RootDirStartSec;              /* For all the sectors in root directory       */
+         sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec);
+         sec_num++) {
+           
+
+        MS_BulkRecv(sec_num, 1, FATBuffer);                  /* Read one sector                             */
+        buf = FATBuffer;
+        while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) {
+            ent_type = FAT_ChkEntType(buf);                  /* Check for the entry type                    */
+            if (ent_type == SFN_ENTRY) {                     /* If it is short entry get short file name    */
+                FAT_GetSFN(buf, ent_name_read);
+                                                    /* Compare given name with this name case insensitively */
+                if (FAT_StrCaseCmp(ent_name_given, ent_name_read) == MATCH_FOUND) {
+                    entry->CurrClus = ReadLE16U(&buf[26]);   /* If they are same, get starting cluster      */
+                    entry->FileSize  = ReadLE32U(&buf[28]);  /* Get file size                               */
+                    entry->EntrySec = sec_num;           /* Get sector number where the filename is located */
+                                                 /* Get offset in this sector where the filename is located */
+                    entry->EntrySecOffset = buf - FATBuffer;
+                    return (MATCH_FOUND);
+                }
+            }
+            if (ent_type == LAST_ENTRY) {    /* If it is the last entry, no more entries will exist. Return */
+                return (MATCH_NOT_FOUND);
+            }
+            buf = buf + 32;                                  /* Move to the next entry                      */
+        }
+    }
+    return (MATCH_NOT_FOUND);
+}
+
+/*
+**************************************************************************************************************
+*                                       GET SHORT FILE NAME AND EXTENSION OF A FILE
+*
+* Description: This function reads the short file name and extension corresponding to a file
+*
+* Arguments  : ent_buf    buffer which contains the 32 byte entry of a file
+*              name       buffer to store the file name and extension of a file
+*
+* Returns    : None
+*
+**************************************************************************************************************
+*/
+
+void  FAT_GetSFN (volatile  USB_INT08U  *entry,
+                            USB_INT08U  *name)
+{
+    USB_INT08U   ext[4];                          /* Buffer to store the extension of a file                */
+    USB_INT08U  *ext_ptr;
+
+
+    ext_ptr = ext;
+
+    FAT_GetSfnName(entry, name);                  /* Get file name into "name" buffer                       */
+    FAT_GetSfnExt(entry, ext_ptr);                /* Get extension into "ext" buffer                        */
+
+    while (*name) {                               /* Goto the end of the filename                           */
+        name++;
+    }
+    if (*ext_ptr) {                               /* If the extension exists, put a '.' charecter           */
+        *name = '.';
+        name++;
+    }
+    while (*ext_ptr) {                            /* Append the extension to the file name                  */
+        *name = *ext_ptr;
+        name++;
+        ext_ptr++;
+    }
+    *name = '\0';
+}
+
+/*
+**************************************************************************************************************
+*                                          GET SHORT FILE NAME OF A FILE
+*
+* Description: This function reads the short file name of a file
+*
+* Arguments  : ent_buf  buffer which contains the 32 byte entry of a file
+*              name     buffer to store the short file name of a file
+*
+* Returns    : None
+*
+**************************************************************************************************************
+*/
+
+void  FAT_GetSfnName (volatile  USB_INT08U  *entry,
+                                USB_INT08U  *name)
+{
+    USB_INT32U  cnt;
+
+
+    cnt = 0;
+    while (cnt < 8) {
+        *name = *entry;                     /* Get first 8 charecters of an SFN entry                       */
+        name++;
+        entry++;
+        cnt++;
+    }
+    *name = 0;
+    name--;
+    while (*name == 0x20) {                 /* If any spaces exist after the file name, replace them with 0 */
+        *name = 0;
+        name--;
+    }
+}
+
+/*
+**************************************************************************************************************
+*                                       GET EXTENSION OF A FILE
+*
+* Description: This function reads the extension of a file
+*
+* Arguments  : ent_buf    buffer which contains the 32 byte entry of a file
+*              ext_ptr    buffer to store the extension of a file       
+*
+* Returns    : None
+*
+**************************************************************************************************************
+*/
+
+void  FAT_GetSfnExt (volatile  USB_INT08U  *entry,
+                               USB_INT08U  *ext_ptr)
+{
+    USB_INT32U  cnt;
+
+
+    cnt = 0;
+    while (cnt < 8) {                  /* Goto the beginning of the file extension                          */
+        entry++;
+        cnt++;
+    }
+    cnt = 0;
+    while (cnt < 3) {                  /* Get 3 charecters from there                                       */
+        *ext_ptr = *entry;
+        ext_ptr++;
+        entry++;
+        cnt++;
+    }
+    *ext_ptr = 0;
+    ext_ptr--;
+    while (*ext_ptr == ' ') {          /* If any spaces exist after the file extension, replace them with 0 */
+        *ext_ptr = 0;
+        ext_ptr--;
+    }
+}
+
+/*
+**************************************************************************************************************
+*                                       CASE INSENSITIVE COMPARISION OF STRINGS
+*
+* Description: This function compares two strings case insensitively
+*
+* Arguments  : str1               Pointer to the first string
+*              str2               Pointer to the second string
+*
+* Returns    : MATCH_FOUND        if both the strings are same
+*              NATCH_NOT_FOUND    if both the strings are different
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S  FAT_StrCaseCmp (USB_INT08U  *str1,
+                            USB_INT08U  *str2)
+{
+    while (*str1 && *str2) {
+        if (*str1 == *str2 || *str1 == (*str2 + 32) || *str1 == (*str2 - 32)) {
+            str1++;
+            str2++;
+            continue;
+        } else {
+            return (MATCH_NOT_FOUND);
+        }
+    }
+    if (*str1 == 0 && *str2 == 0) {
+        return (MATCH_FOUND);
+    } else {
+        return (MATCH_NOT_FOUND);
+    }
+}
+
+/*
+**************************************************************************************************************
+*                                       CHECK TYPE OF THE ENTRY
+*
+* Description: This function checks the type of file entry.
+*
+* Arguments  : ent           Pointer to the buffer containing the entry
+*
+* Returns    : LAST_ENTRY    if the entry is last entry
+*              FREE_ENTRY    if the entry is free entry
+*              LFN_ENTRY     if the entry is long file name entry
+*              SFN_ENTRY     if the entry is short file name entry
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U  FAT_ChkEntType (volatile  USB_INT08U  *ent)
+{
+    if (ent[0] == 0x00) {                              /* First byte is 0 means it is the last entry        */
+        return (LAST_ENTRY);
+    }
+
+    if (ent[0] == 0xE5) {                              /* First byte is 0xE5 means it is the free entry     */
+        return (FREE_ENTRY);
+    }
+
+    if (0x0F == ent[11]) {                             /* If 11th byte of an entry is 0x0F, it is LFN       */
+        return (LFN_ENTRY);
+
+    } else {
+        return (SFN_ENTRY);                            /* Else it is the SFN                                */
+    }
+}
+
+/*
+**************************************************************************************************************
+*                                       READ DATA REQUESTED BY THE USER
+*
+* Description: This function reads data requested by the application from the file pointed by file descriptor.
+*
+* Arguments  : fd                  file descriptor that points to a file
+*              buffer              buffer into which the data is to be read
+*              num_bytes           number of bytes requested by the application
+*
+* Returns    : total_bytes_read    Total bytes actually read.
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U  FILE_Read (          USB_INT32S  fd,
+                       volatile  USB_INT08U  *buffer,
+                                 USB_INT32U   num_bytes)
+{
+    USB_INT32U   total_bytes_to_read;            /* Total bytes requested by the application                */
+    USB_INT32U   total_bytes_read;               /* Total bytes read                                        */
+    USB_INT32U   bytes_read;                     /* Bytes read from one cluster                             */
+    USB_INT32U   bytes_to_read;                  /* Bytes to be read in one cluster                         */
+    FILE_ENTRY  *entry;                          /* Entry that contains the file attribute information      */
+    USB_INT16U   next_clus;                     /* Next cluster of the current cluster in the cluster chain */
+
+    entry = &FAT_FileEntry[fd-1];                /* Get file entry from file descriptor                     */
+    total_bytes_read = 0;
+
+    if (entry->FileSize == 0) {
+        return (0);
+    }
+    if (num_bytes < entry->FileSize) {
+        total_bytes_to_read = num_bytes;
+    } else {
+        total_bytes_to_read = entry->FileSize;
+    }
+    do {
+        next_clus = FAT_GetNextClus(entry->CurrClus);     /* Get next cluster                               */
+        if (next_clus == 0) {                             /* If the current cluster is the last cluster     */
+                                                          /* If the offset is at the end of the file        */
+            if (entry->CurrClusOffset == (entry->FileSize % FAT_BootSec.BytsPerClus)) {
+                return (0);                               /* No more bytes to read                          */
+            }                               /* If requested number is > remaining bytes in the last cluster */
+            if (total_bytes_to_read > ((entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset)) {
+                total_bytes_to_read = (entry->FileSize % FAT_BootSec.BytsPerClus) - entry->CurrClusOffset;
+            }
+            bytes_to_read = total_bytes_to_read;
+                                         /* If requested number is > remaining bytes in the current cluster */
+        } else if (total_bytes_to_read > (FAT_BootSec.BytsPerClus - entry->CurrClusOffset)) {
+            bytes_to_read = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
+        } else {
+            bytes_to_read = total_bytes_to_read;
+        }
+        bytes_read = FAT_ClusRead(entry->CurrClus,       /* Read bytes from a single cluster                */
+                                  entry->CurrClusOffset,
+                                  buffer,
+                                  bytes_to_read);
+        buffer              += bytes_read;
+        total_bytes_read    += bytes_read;
+        total_bytes_to_read -= bytes_read;
+                                             /* If the cluster offset reaches end of the cluster, make it 0 */
+        if (entry->CurrClusOffset + bytes_read == FAT_BootSec.BytsPerClus) {
+            entry->CurrClusOffset = 0;
+        } else {
+            entry->CurrClusOffset += bytes_read;        /* Else increment the cluster offset                */
+        }
+        if (entry->CurrClusOffset == 0) {
+            entry->CurrClus = (next_clus > 0) ? next_clus : entry->CurrClus;
+        }
+    } while (total_bytes_to_read);
+    return (total_bytes_read);
+}
+
+/*
+**************************************************************************************************************
+*                                                 READ FROM ONE CLUSTER
+*
+* Description: This function reads the data from a single cluster.
+*
+* Arguments  : curr_clus         Current cluster from which the data has to read
+*              clus_offset       Position in the current cluster from which the data has to read
+*              buffer            Buffer into which the data has to read
+*              num_bytes         Number of bytes to read
+*
+* Returns    : tot_bytes_read    Total bytes read from the current cluster
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U  FAT_ClusRead (          USB_INT16U   curr_clus,
+                                    USB_INT32U   clus_offset,
+                          volatile  USB_INT08U  *buffer,
+                                    USB_INT32U   num_bytes)
+{
+    USB_INT32U  tot_bytes_read;                              /* total bytes read in the current cluster     */
+    USB_INT32U  n_bytes;                                     /* Bytes to read in the current sector         */
+    USB_INT32U  start_sec;                                   /* Starting sector of the current cluster      */
+    USB_INT32U  sec_num;                                     /*Current sector number                        */
+    USB_INT16U  num_sec;                                     /* Number of sectors to be read                */
+    USB_INT32U  sec_offset;                                  /* Offset in the current sector                */
+    USB_INT32U  cnt;
+
+
+    tot_bytes_read = 0;
+    start_sec  = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
+    sec_num    = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
+    num_sec    = num_bytes / FAT_BootSec.BytsPerSec;
+    sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
+
+    if (sec_offset) {                                 /* If the sector offset is at the middle of a sector  */
+        MS_BulkRecv(sec_num, 1, FATBuffer);           /* Read the first sector                              */
+        n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
+                  (FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
+        for (cnt = sec_offset; cnt < sec_offset + n_bytes; cnt++) {
+            *buffer = FATBuffer[cnt];                 /* Copy the required bytes to user buffer             */
+             buffer++;
+        }
+        tot_bytes_read += n_bytes;
+        clus_offset    += n_bytes;
+        num_bytes      -= n_bytes;
+        sec_num++;
+    }
+
+    if (num_bytes / FAT_BootSec.BytsPerSec) {         /* Read all the remaining full sectors                */
+
+        num_sec = num_bytes / FAT_BootSec.BytsPerSec;
+        MS_BulkRecv(sec_num, num_sec, buffer);
+        buffer         += (num_sec * FAT_BootSec.BytsPerSec);
+        tot_bytes_read += (num_sec * FAT_BootSec.BytsPerSec);
+        clus_offset    += (num_sec * FAT_BootSec.BytsPerSec);
+        num_bytes      -= (num_sec * FAT_BootSec.BytsPerSec);
+        sec_num        += num_sec;
+    }
+
+    if (num_bytes) {                                  /* Read the last sector for the remaining bytes       */
+        MS_BulkRecv(sec_num, 1, FATBuffer);
+        for (cnt = 0; cnt < num_bytes; cnt++) {
+            *buffer = FATBuffer[cnt];                 /* Copy the required bytes to user buffer             */
+             buffer++;
+        }
+        tot_bytes_read += num_bytes;
+    }
+
+    return (tot_bytes_read);
+}
+
+/*
+**************************************************************************************************************
+*                                       WRITE THE DATA REQUESTED BY THE USER
+*
+* Description: This function writes data requested by the application to the file pointed by file descriptor
+*
+* Arguments  : fd                     file descriptor that points to a file
+*              buffer                 buffer from which the data is to be written
+*              num_bytes              number of bytes requested by the application
+*
+* Returns    : total_bytes_written    Total bytes actually written
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U  FILE_Write (          USB_INT32S  fd,
+                        volatile  USB_INT08U  *buffer,
+                                  USB_INT32U   num_bytes)
+{
+    USB_INT32U   total_bytes_to_write;                      /* Total bytes requested by application         */
+    USB_INT32U   total_bytes_written;                       /* Total bytes written                          */
+    USB_INT32U   bytes_written;                             /* Bytes written in a single cluster            */
+    USB_INT32U   bytes_to_write;                            /* Bytes to write in a single cluster           */
+    FILE_ENTRY  *entry;                               /* Entry that contains the file attribute information */
+    USB_INT16U   free_clus;                                 /* Free cluster available in the disk           */
+
+
+    entry = &FAT_FileEntry[fd-1];                           /* Get file entry from file descriptor                     */
+    total_bytes_written  = 0;
+    total_bytes_to_write = num_bytes;
+
+    if (num_bytes) {
+        if (entry->FileSize == 0) {
+            free_clus = FAT_GetFreeClus();
+            FAT_UpdateFAT(free_clus, 0xFFFF);
+            entry->CurrClus  = free_clus;
+            MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
+            WriteLE16U(&FATBuffer[(entry->EntrySecOffset) + 26], free_clus);
+            MS_BulkSend(entry->EntrySec, 1, FATBuffer);
+        }
+    } else {
+        return (0);
+    }
+    entry->CurrClus = FAT_GetEndClus(entry->CurrClus);           /* Make the current cluster as end cluster */
+    entry->CurrClusOffset = entry->FileSize % FAT_BootSec.BytsPerClus;   /* Move cluster offset to file end */
+    do {
+        if (total_bytes_to_write > FAT_BootSec.BytsPerClus - entry->CurrClusOffset) {
+            bytes_to_write = FAT_BootSec.BytsPerClus - entry->CurrClusOffset;
+        } else {
+            bytes_to_write = total_bytes_to_write;
+        }
+        bytes_written = FAT_ClusWrite(entry->CurrClus,
+                                      entry->CurrClusOffset,
+                                      buffer,
+                                      bytes_to_write);
+        buffer               += bytes_written;
+        total_bytes_written  += bytes_written;
+        total_bytes_to_write -= bytes_written;
+        entry->FileSize      += bytes_written;
+        if (entry->CurrClusOffset + bytes_written == FAT_BootSec.BytsPerClus) {
+            entry->CurrClusOffset = 0;
+        } else {
+            entry->CurrClusOffset += bytes_written;
+        }
+        if (entry->CurrClusOffset == 0) {
+            free_clus = FAT_GetFreeClus();
+            if (free_clus == 0) {
+                return (total_bytes_written);
+            }
+            FAT_UpdateFAT(entry->CurrClus, free_clus);
+            FAT_UpdateFAT(free_clus, 0xFFFF);
+            entry->CurrClus = free_clus;
+        }
+    } while (total_bytes_to_write);
+    return (total_bytes_written);
+}
+
+/*
+**************************************************************************************************************
+*                                               WRITE TO ONE CLUSTER
+*
+* Description: This function writes the data to a single cluster.
+*
+* Arguments  : curr_clus         Current cluster into which the data has to write
+*              clus_offset       Position in the current cluster from which the data has to write
+*              buffer            Buffer from which the data has to write
+*              num_bytes         Number of bytes to write
+*
+* Returns    : tot_bytes_read    Total bytes written into the current cluster
+*
+**************************************************************************************************************
+*/
+
+USB_INT32U  FAT_ClusWrite (          USB_INT16U   curr_clus,
+                                     USB_INT32U   clus_offset,
+                           volatile  USB_INT08U  *buffer,
+                                     USB_INT32U   num_bytes)
+{
+    USB_INT32U  tot_bytes_written;
+	USB_INT32U  n_bytes;
+	USB_INT32U  start_sec;
+	USB_INT32U  sec_num;
+	USB_INT16U  num_sec;
+	USB_INT32U  sec_offset;
+	USB_INT32U  cnt;
+
+
+	tot_bytes_written = 0;
+	start_sec  = ((curr_clus - 2) * FAT_BootSec.SecPerClus) + FAT_BootSec.FirstDataSec;
+	sec_num    = start_sec + (clus_offset / FAT_BootSec.BytsPerSec);
+	num_sec    = num_bytes / FAT_BootSec.BytsPerSec;
+	sec_offset = clus_offset % FAT_BootSec.BytsPerSec;
+
+	if (sec_offset) {
+        MS_BulkRecv(sec_num, 1, FATBuffer);
+		n_bytes = (FAT_BootSec.BytsPerSec - sec_offset <= num_bytes) ?
+                  (FAT_BootSec.BytsPerSec - sec_offset) : num_bytes;
+		for (cnt = sec_offset; cnt < (sec_offset + n_bytes); cnt++) {
+            FATBuffer[cnt] = *buffer;
+			buffer++;
+		}
+        MS_BulkSend(sec_num, 1, FATBuffer);
+		tot_bytes_written += n_bytes;
+		clus_offset       += n_bytes;
+        num_bytes         -= n_bytes;
+		sec_num++;
+	}
+	if (num_bytes / FAT_BootSec.BytsPerSec) {
+		num_sec = num_bytes / FAT_BootSec.BytsPerSec;
+		MS_BulkSend(sec_num, num_sec, buffer);
+		buffer            += (num_sec * FAT_BootSec.BytsPerSec);
+		tot_bytes_written += (num_sec * FAT_BootSec.BytsPerSec);
+		clus_offset       += (num_sec * FAT_BootSec.BytsPerSec);
+        num_bytes         -= (num_sec * FAT_BootSec.BytsPerSec);
+		sec_num           += num_sec;
+	}
+	if (num_bytes) {
+        MS_BulkRecv(sec_num, 1, FATBuffer);
+
+		for (cnt = 0; cnt < num_bytes; cnt++) {
+			FATBuffer[cnt] = *buffer;
+			buffer++;
+		}
+        MS_BulkSend(sec_num, 1, FATBuffer);
+		tot_bytes_written += num_bytes;
+	}
+	return (tot_bytes_written);
+}
+
+/*
+**************************************************************************************************************
+*                                              GET NEXT CLUSTER
+*
+* Description: This function returns next cluster of the current cluster in the cluster chain. If the current
+*              cluster is the last cluster then this function returns 0
+*
+* Arguments  : clus_no    The cluster number for which the next cluster to be found
+*
+* Returns    : next_clus  if the current cluster is not the last cluster
+*              0          if the current cluster is the last cluster
+*                         Note: In practical cluster number 0 doesn't exist
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U  FAT_GetNextClus (USB_INT16U  clus_no)
+{
+    USB_INT32U  sec_num;
+    USB_INT32U  ent_offset;
+    USB_INT16U  next_clus;
+
+                                          /* Get the sector number in the FAT that contains current cluster */
+    sec_num = FAT_BootSec.RsvdSecCnt + ((clus_no * 2) / FAT_BootSec.BytsPerSec);
+                                   /* Get the sector offset in the FAT where the current cluster is located */
+    ent_offset = (clus_no * 2) % FAT_BootSec.BytsPerSec; 
+    MS_BulkRecv(sec_num, 1, FATBuffer);                          /* Read that sector                        */
+    next_clus = ReadLE16U(&FATBuffer[ent_offset]);               /* Read the next cluster                   */
+    if (next_clus >= 0xFFF8 && next_clus <= 0xFFFF) {      /* If that value is in between 0xFFF8 and 0xFFFF */ 
+        next_clus = 0;                                     /* Current cluster is the end cluster            */
+    }
+    return (next_clus);
+
+}
+
+/*
+**************************************************************************************************************
+*                                               GET FREE CLUSTER
+*
+* Description: This function returns the free cluster if available
+*
+* Arguments  : None
+*
+* Returns    : free_clus    if available
+*              0            if not available(means the disk is full)
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U  FAT_GetFreeClus (void)
+{
+    USB_INT32U  num_sec;
+    USB_INT32U  cnt;
+    USB_INT32U  sec_num;
+    USB_INT16U  free_clus;
+
+
+    sec_num = FAT_BootSec.RsvdSecCnt;
+    num_sec = FAT_BootSec.FATSz16;
+    while (sec_num < (FAT_BootSec.RsvdSecCnt + num_sec)) {
+        MS_BulkRecv(sec_num, 1, FATBuffer);
+        for (cnt = 0; cnt < FAT_BootSec.BytsPerSec; cnt += 2) {
+            if (ReadLE16U(&FATBuffer[cnt]) == 0) {
+                free_clus = (((sec_num - FAT_BootSec.RsvdSecCnt) * FAT_BootSec.BytsPerSec) + cnt) / 2;
+                return (free_clus);
+            }
+        }
+        sec_num++;
+    }
+    return (0);
+}
+
+/*
+**************************************************************************************************************
+*                                       UPDATE FILE ALLOCATION TABLE
+*
+* Description: This function updates the file allocation table
+*
+* Arguments  : curr_clus    Offset of the current cluster number in the file allocation table
+*              value        Value with which this offset to be updated
+*
+* Returns    : None
+*
+**************************************************************************************************************
+*/
+
+void  FAT_UpdateFAT (USB_INT16U  curr_clus,
+                     USB_INT16U  value)
+{
+    USB_INT32U  sec_num;
+    USB_INT32U  sec_offset;
+    
+    sec_num = FAT_BootSec.RsvdSecCnt + (curr_clus * 2) / FAT_BootSec.BytsPerSec;
+    sec_offset = (curr_clus * 2) % FAT_BootSec.BytsPerSec;
+    
+    MS_BulkRecv(sec_num, 1, FATBuffer);
+    WriteLE16U(&FATBuffer[sec_offset], value);
+    MS_BulkSend(sec_num, 1, FATBuffer);
+}
+
+/*
+**************************************************************************************************************
+*                                              UPDATE THE FILE ENTRY
+*
+* Description: This function updates the file entry that is located in the root directory
+*
+* Arguments  : entry    Pointer to the FILE ENTRY structure which contains the information about the file
+*
+* Returns    : None
+*
+**************************************************************************************************************
+*/
+
+void  FAT_UpdateEntry (FILE_ENTRY  *entry)
+{
+    USB_INT32U  sec_num;
+    USB_INT32U  offset;
+    
+    sec_num = entry->EntrySec;
+    offset  = entry->EntrySecOffset;
+    MS_BulkRecv(sec_num, 1, FATBuffer);
+    WriteLE32U(&FATBuffer[offset + 28], entry->FileSize);
+    MS_BulkSend(sec_num, 1, FATBuffer);
+}
+
+/*
+**************************************************************************************************************
+*                                              CREATING AN ENTRY
+*
+* Description: This function creates a file entry in the root directory if the file does not exist
+*
+* Arguments  : ent_name_given    The file name with which the entry is to be created
+*              entry             Pointer to FILE ENTRY structure
+*
+* Returns    : OK                If the entry already exists or successfully created if it doesn't exists
+*              ERROR             If failed to create the entry
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S  FAT_CreateEntry (USB_INT08U  *ent_name_given,
+                             FILE_ENTRY  *entry)
+{
+    USB_INT32S  rc;
+
+
+    rc = FAT_FindEntry(ent_name_given, entry);        /* Find for the given file name in the root directory */
+    if (rc == MATCH_FOUND) {                          /* If match found, return                             */
+        return (rc);
+    } else {
+        rc = FAT_GetFreeEntry(entry);                 /* Else get a free entry from the root directory      */
+        if (rc != OK) {
+            return (rc);
+        } else {
+            FAT_PutSFN(ent_name_given, entry);        /* Store the given short file name in that entry      */
+            return (rc);
+        }
+    }
+}
+
+/*
+**************************************************************************************************************
+*                                                GET GREE ENTRY
+*
+* Description: This function searches for a free entry in the root directory. If a free entry is found, the
+*              sector number and sector offset where the entry is located will be stored
+*
+* Arguments  : entry    Pointer to FILE_ENTRY structure
+*
+* Returns    : OK       If a free entry is found
+*              ERROR    If no free entry is found
+*
+**************************************************************************************************************
+*/
+
+USB_INT32S  FAT_GetFreeEntry (FILE_ENTRY  *entry)
+{
+              USB_INT32U   sec_num;
+    volatile  USB_INT08U  *buf;
+              USB_INT08U   ent_type;
+
+
+    for (sec_num = FAT_BootSec.RootDirStartSec; 
+         sec_num < (FAT_BootSec.RootDirStartSec + FAT_BootSec.RootDirSec);
+         sec_num++) {
+
+        MS_BulkRecv(sec_num, 1, FATBuffer);
+        buf = FATBuffer;
+        while (buf < (FATBuffer + FAT_BootSec.BytsPerSec)) {
+            ent_type = FAT_ChkEntType(buf);
+            if (ent_type == FREE_ENTRY) {
+                entry->EntrySec       = sec_num;
+                entry->EntrySecOffset = buf - FATBuffer;
+                return (OK);
+            }
+            if (ent_type == LAST_ENTRY) {
+                return (ERR_ROOT_DIR_FULL);
+            } else {
+                buf += 32;
+            }
+        }
+    }
+    return (ERR_ROOT_DIR_FULL);
+}
+
+/*
+**************************************************************************************************************
+*                                              PUT SHORT FILE NAME
+*
+* Description: This function fills the file entry with the short file name given by the user
+*
+* Arguments  : ent_name_given    File name given by the user
+*              entry             Pointer to the FILE_ENTRY structure
+*
+* Returns    : None
+*
+**************************************************************************************************************
+*/
+
+void  FAT_PutSFN (USB_INT08U  *ent_name_given,
+                  FILE_ENTRY  *entry)
+{
+    USB_INT32U  idx;
+
+                                           /* Read the sector from root directory containing the free entry */
+    MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
+    for (idx = 0; idx < 8; idx++) {        /* Fill the first eight charecters of the entry with file name   */
+        if (*ent_name_given == '.') {
+            while (idx < 8) {
+                FATBuffer[entry->EntrySecOffset + idx] = 0x20;
+                idx++;
+            }
+            ent_name_given++;
+        } else {
+            FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
+            ent_name_given++;
+        }
+    }
+
+    for (idx = 8; idx < 11; idx++) {                      /* Fill the next 3 charecters with file extension */
+        if (*ent_name_given == '.') {
+            while (idx < 11) {
+                FATBuffer[entry->EntrySecOffset + idx] = 0x20;
+                idx++;
+            }
+        } else {
+            FATBuffer[entry->EntrySecOffset + idx] = *ent_name_given;
+            ent_name_given++;
+        }
+    }
+    FATBuffer[entry->EntrySecOffset + idx] = 0x20;
+    for (idx = 12; idx < 32; idx++) {                           /* Fill all the remaining bytes with 0's    */
+        FATBuffer[entry->EntrySecOffset + idx] = 0;
+    }
+    MS_BulkSend(entry->EntrySec, 1, FATBuffer);                 /* Write the sector into the root directory */
+}
+
+/*
+**************************************************************************************************************
+*                                                  FILE CLOSE
+*
+* Description: This function closes the opened file by making all the elements of FILE_ENTRY structure to 0
+*
+* Arguments  : fd    File descriptor which points to the file to be closed
+*
+* Returns    : None
+*
+**************************************************************************************************************
+*/
+
+void  FILE_Close (USB_INT32S  fd)
+{
+    FILE_ENTRY  *entry;
+
+
+    entry = &FAT_FileEntry[fd-1];
+    MS_BulkRecv(entry->EntrySec, 1, FATBuffer);
+    WriteLE32U(&FATBuffer[entry->EntrySecOffset + 28], entry->FileSize);    /* Update the file size         */
+    MS_BulkSend(entry->EntrySec, 1, FATBuffer);
+    entry->CurrClus       = 0;
+    entry->CurrClusOffset = 0;
+    entry->FileSize       = 0;
+    entry->EntrySec       = 0;
+    entry->EntrySecOffset = 0;
+    entry->FileStatus     = 0;
+}
+
+/*
+**************************************************************************************************************
+*                                               GET END CLUSTER
+*
+* Description: This function end cluster in the cluster chain of a cluster
+*
+* Arguments  : clus_no    Starting cluster of the cluster chain in which end cluster to be found
+*
+* Returns    : End cluster in the cluster chain
+*
+**************************************************************************************************************
+*/
+
+USB_INT16U  FAT_GetEndClus (USB_INT16U  clus_no)
+{
+    USB_INT16U  next_clus;
+
+
+    next_clus = clus_no;
+    while (next_clus) {
+        next_clus = FAT_GetNextClus(clus_no);
+        if (next_clus) {
+            clus_no = next_clus;
+        }
+    }
+    return (clus_no);
+}