Webserver+3d print

Dependents:   Nucleo

Revision:
0:8918a71cdbe9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/fs_port_fatfs.c	Sat Feb 04 18:15:49 2017 +0000
@@ -0,0 +1,764 @@
+/**
+ * @file fs_port_fatfs.c
+ * @brief File system abstraction layer (FatFs)
+ *
+ * @section License
+ *
+ * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * @author Oryx Embedded SARL (www.oryx-embedded.com)
+ * @version 1.7.6
+ **/
+
+//Dependencies
+#include <string.h>
+#include "fs_port.h"
+#include "error.h"
+#include "debug.h"
+
+//FatFs specific headers
+#include "ff.h"
+
+//File system objects
+static FATFS fs;
+static FIL fileTable[FS_MAX_FILES];
+static DIR dirTable[FS_MAX_DIRS];
+
+//Mutex that protects critical sections
+static OsMutex fsMutex;
+
+
+/**
+ * @brief File system initialization
+ * @return Error code
+ **/
+
+error_t fsInit(void)
+{
+   FRESULT res;
+
+   //Clear file system objects
+   memset(fileTable, 0, sizeof(fileTable));
+   memset(dirTable, 0, sizeof(dirTable));
+
+   //Create a mutex to protect critical sections
+   if(!osCreateMutex(&fsMutex))
+   {
+      //Failed to create mutex
+      return ERROR_OUT_OF_RESOURCES;
+   }
+
+//Revision 0.09b or lower?
+#if (_FATFS == 124 || _FATFS == 126 || _FATFS == 8085 || _FATFS == 8255 || \
+   _FATFS == 8237 || _FATFS == 6502 || _FATFS == 4004 || _FATFS == 82786)
+   //Mount file system
+   res = f_mount(0, &fs);
+//Revision 0.10 or higher?
+#else
+   //Mount file system
+   res = f_mount(&fs, "", 1);
+#endif
+
+   //Failed to mount file system?
+   if(res != FR_OK)
+   {
+      //Clean up side effects
+      osDeleteMutex(&fsMutex);
+      //Report an error
+      return ERROR_FAILURE;
+   }
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Check whether a file exists
+ * @param[in] path NULL-terminated string specifying the filename
+ * @return The function returns TRUE if the file exists. Otherwise FALSE is returned
+ **/
+
+bool_t fsFileExists(const char_t *path)
+{
+   FRESULT res;
+   FILINFO fno;
+
+//Long filename support?
+#if (_USE_LFN != 0)
+   fno.lfname = NULL;
+   fno.lfsize = 0;
+#endif
+
+   //Make sure the pathname is valid
+   if(path == NULL)
+      return FALSE;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Check whether the file exists
+   res = f_stat(path, &fno);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return FALSE;
+
+   //Valid file?
+   if(fno.fattrib & AM_DIR)
+      return FALSE;
+   else
+      return TRUE;
+}
+
+
+/**
+ * @brief Retrieve the size of the specified file
+ * @param[in] path NULL-terminated string specifying the filename
+ * @param[out] size Size of the file in bytes
+ * @return Error code
+ **/
+
+error_t fsGetFileSize(const char_t *path, uint32_t *size)
+{
+   FRESULT res;
+   FILINFO fno;
+
+//Long filename support?
+#if (_USE_LFN != 0)
+   fno.lfname = NULL;
+   fno.lfsize = 0;
+#endif
+
+   //Check parameters
+   if(path == NULL || size == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Retrieve information about the specified file
+   res = f_stat(path, &fno);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+   //Valid file?
+   if(fno.fattrib & AM_DIR)
+      return ERROR_FAILURE;
+
+   //Return the size of the file
+   *size = fno.fsize;
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Rename the specified file
+ * @param[in] oldPath NULL-terminated string specifying the pathname of the file to be renamed
+ * @param[in] newPath NULL-terminated string specifying the new filename
+ * @return Error code
+ **/
+
+error_t fsRenameFile(const char_t *oldPath, const char_t *newPath)
+{
+   FRESULT res;
+
+   //Check parameters
+   if(oldPath == NULL || newPath == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Rename the specified file
+   res = f_rename(oldPath, newPath);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Delete a file
+ * @param[in] path NULL-terminated string specifying the filename
+ * @return Error code
+ **/
+
+error_t fsDeleteFile(const char_t *path)
+{
+   FRESULT res;
+
+   //Make sure the pathname is valid
+   if(path == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Delete the specified file
+   res = f_unlink(path);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Open the specified file for reading or writing
+ * @param[in] path NULL-terminated string specifying the filename
+ * @param[in] mode Type of access permitted (FS_FILE_MODE_READ,
+ *   FS_FILE_MODE_WRITE or FS_FILE_MODE_CREATE)
+ * @return File handle
+ **/
+
+FsFile *fsOpenFile(const char_t *path, uint_t mode)
+{
+   uint_t i;
+   uint_t flags;
+   FRESULT res;
+
+   //File pointer
+   FsFile *file = NULL;
+
+   //Make sure the pathname is valid
+   if(path == NULL)
+      return NULL;
+
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+
+   //Loop through the file objects
+   for(i = 0; i < FS_MAX_FILES; i++)
+   {
+      //Unused file object found?
+      if(fileTable[i].fs == NULL)
+      {
+         //Default access mode
+         flags = 0;
+
+         //Check access mode
+         if(mode & FS_FILE_MODE_READ)
+            flags |= FA_READ;
+         if(mode & FS_FILE_MODE_WRITE)
+            flags |= FA_WRITE;
+         if(mode & FS_FILE_MODE_CREATE)
+            flags |= FA_OPEN_ALWAYS;
+         if(mode & FS_FILE_MODE_TRUNC)
+            flags |= FA_CREATE_ALWAYS;
+
+         //Open the specified file
+         res = f_open(&fileTable[i], path, flags);
+
+         //Check status code
+         if(res == FR_OK)
+            file = &fileTable[i];
+
+         //Stop immediately
+         break;
+      }
+   }
+
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+   //Return a handle to the file
+   return file;
+}
+
+
+/**
+ * @brief Move to specified position in file
+ * @param[in] file Handle that identifies the file
+ * @param[in] offset Number of bytes to move from origin
+ * @param[in] origin Position used as reference for the offset (FS_SEEK_SET,
+ *   FS_SEEK_CUR or FS_SEEK_END)
+ * @return Error code
+ **/
+
+error_t fsSeekFile(FsFile *file, int_t offset, uint_t origin)
+{
+   FRESULT res;
+
+   //Make sure the file pointer is valid
+   if(file == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Offset is relative to the current file pointer position?
+   if(origin == FS_SEEK_CUR)
+      offset += f_tell((FIL *) file);
+   //Offset is relative to the end of the file?
+   else if(origin == FS_SEEK_END)
+      offset += f_size((FIL *) file);
+
+   //Move read/write pointer
+   res = f_lseek((FIL *) file, offset);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Write data to the specified file
+ * @param[in] file Handle that identifies the file to be written
+ * @param[in] data Pointer to a buffer containing the data to be written
+ * @param[in] length Number of data bytes to write
+ * @return Error code
+ **/
+
+error_t fsWriteFile(FsFile *file, void *data, size_t length)
+{
+   UINT n;
+   FRESULT res;
+
+   //Make sure the file pointer is valid
+   if(file == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Write data
+   res = f_write((FIL *) file, data, length, &n);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //Sanity check
+   if(n != length)
+      return ERROR_FAILURE;
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Read data from the specified file
+ * @param[in] file Handle that identifies the file to be read
+ * @param[in] data Pointer to the buffer where to copy the data
+ * @param[in] size Size of the buffer, in bytes
+ * @param[out] length Number of data bytes that have been read
+ * @return Error code
+ **/
+
+error_t fsReadFile(FsFile *file, void *data, size_t size, size_t *length)
+{
+   UINT n;
+   FRESULT res;
+
+   //No data has been read yet
+   *length = 0;
+
+   //Make sure the file pointer is valid
+   if(file == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Read data
+   res = f_read((FIL *) file, data, size, &n);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //End of file?
+   if(!n)
+      return ERROR_END_OF_FILE;
+
+   //Total number of data that have been read
+   *length = n;
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Close a file
+ * @param[in] file Handle that identifies the file to be closed
+ **/
+
+void fsCloseFile(FsFile *file)
+{
+   //Make sure the file pointer is valid
+   if(file != NULL)
+   {
+      //Enter critical section
+      osAcquireMutex(&fsMutex);
+
+      //Close the specified file
+      f_close((FIL *) file);
+      //Mark the corresponding entry as free
+      ((FIL *) file)->fs = NULL;
+
+      //Leave critical section
+      osReleaseMutex(&fsMutex);
+   }
+}
+
+
+/**
+ * @brief Check whether a directory exists
+ * @param[in] path NULL-terminated string specifying the directory path
+ * @return The function returns TRUE if the directory exists. Otherwise FALSE is returned
+ **/
+
+bool_t fsDirExists(const char_t *path)
+{
+   FRESULT res;
+   FILINFO fno;
+
+//Long filename support?
+#if (_USE_LFN != 0)
+   fno.lfname = NULL;
+   fno.lfsize = 0;
+#endif
+
+   //Make sure the pathname is valid
+   if(path == NULL)
+      return FALSE;
+
+   //Root directory?
+   if(!strcmp(path, "/"))
+      return TRUE;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Check whether the file exists
+   res = f_stat(path, &fno);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return FALSE;
+
+   //Valid directory?
+   if(fno.fattrib & AM_DIR)
+      return TRUE;
+   else
+      return FALSE;
+}
+
+
+/**
+ * @brief Create a directory
+ * @param[in] path NULL-terminated string specifying the directory path
+ * @return Error code
+ **/
+
+error_t fsCreateDir(const char_t *path)
+{
+   FRESULT res;
+
+   //Make sure the pathname is valid
+   if(path == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Create a new directory
+   res = f_mkdir(path);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Remove a directory
+ * @param[in] path NULL-terminated string specifying the directory path
+ * @return Error code
+ **/
+
+error_t fsRemoveDir(const char_t *path)
+{
+   FRESULT res;
+
+   //Make sure the pathname is valid
+   if(path == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Remove the specified directory
+   res = f_unlink(path);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Open a directory stream
+ * @param[in] path NULL-terminated string specifying the directory path
+ * @return Directory handle
+ **/
+
+FsDir *fsOpenDir(const char_t *path)
+{
+   uint_t i;
+   FRESULT res;
+
+   //Directory pointer
+   FsDir *dir = NULL;
+
+   //Make sure the pathname is valid
+   if(path == NULL)
+      return NULL;
+
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+
+   //Loop through the directory objects
+   for(i = 0; i < FS_MAX_DIRS; i++)
+   {
+      //Unused directory object found?
+      if(dirTable[i].fs == NULL)
+      {
+         //Open the specified directory
+         res = f_opendir(&dirTable[i], path);
+
+         //Check status code
+         if(res == FR_OK)
+            dir = &dirTable[i];
+
+         //Stop immediately
+         break;
+      }
+   }
+
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+   //Return a handle to the directory
+   return dir;
+}
+
+
+/**
+ * @brief Read an entry from the specified directory stream
+ * @param[in] dir Handle that identifies the directory
+ * @param[out] dirEntry Pointer to a directory entry
+ * @return Error code
+ **/
+
+error_t fsReadDir(FsDir *dir, FsDirEntry *dirEntry)
+{
+   FRESULT res;
+   FILINFO fno;
+   char_t *fn;
+   size_t n;
+
+//Long filename support?
+#if (_USE_LFN != 0)
+   char_t lfn[_MAX_LFN + 1];
+   fno.lfname = lfn;
+   fno.lfsize = sizeof(lfn);
+#endif
+
+   //Make sure the directory pointer is valid
+   if(dir == NULL)
+      return ERROR_INVALID_PARAMETER;
+
+#if (_FS_REENTRANT == 0)
+   //Enter critical section
+   osAcquireMutex(&fsMutex);
+#endif
+
+   //Read the specified directory
+   res = f_readdir((DIR *) dir, &fno);
+
+#if (_FS_REENTRANT == 0)
+   //Leave critical section
+   osReleaseMutex(&fsMutex);
+#endif
+
+   //Any error to report?
+   if(res != FR_OK)
+      return ERROR_FAILURE;
+
+   //End of the directory stream?
+   if(fno.fname[0] == '\0')
+      return ERROR_END_OF_STREAM;
+
+//Long filename support?
+#if (_USE_LFN != 0)
+   fn = (*fno.lfname != '\0') ? fno.lfname : fno.fname;
+#else
+   fn = fno.fname;
+#endif
+
+   //File attributes
+   dirEntry->attributes = fno.fattrib;
+   //File size
+   dirEntry->size = fno.fsize;
+   //Last modified date
+   dirEntry->modified.year = 1980 + ((fno.fdate >> 9) & 0x7F);
+   dirEntry->modified.month = (fno.fdate >> 5) & 0x0F;
+   dirEntry->modified.day = fno.fdate & 0x1F;
+   dirEntry->modified.dayOfWeek = 0;
+   //Last modified time
+   dirEntry->modified.hours = (fno.ftime >> 11) & 0x1F;
+   dirEntry->modified.minutes = (fno.ftime >> 5) & 0x3F;
+   dirEntry->modified.seconds = (fno.ftime & 0x1F) * 2;
+   dirEntry->modified.milliseconds = 0;
+
+   //Make sure the date is valid
+   dirEntry->modified.month = MAX(dirEntry->modified.month, 1);
+   dirEntry->modified.month = MIN(dirEntry->modified.month, 12);
+   dirEntry->modified.day = MAX(dirEntry->modified.day, 1);
+   dirEntry->modified.day = MIN(dirEntry->modified.day, 31);
+
+   //Retrieve the length of the file name
+   n = strlen(fn);
+   //Limit the number of characters to be copied
+   n = MIN(n, FS_MAX_NAME_LEN);
+
+   //Copy file name
+   strncpy(dirEntry->name, fn, n);
+   //Properly terminate the string with a NULL character
+   dirEntry->name[n] = '\0';
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Close a directory stream
+ * @param[in] dir Handle that identifies the directory to be closed
+ **/
+
+void fsCloseDir(FsDir *dir)
+{
+   //Make sure the directory pointer is valid
+   if(dir != NULL)
+   {
+      //Enter critical section
+      osAcquireMutex(&fsMutex);
+
+#if (_FATFS == 80960)
+      //Close the specified directory
+      f_closedir((DIR *) dir);
+#endif
+      //Mark the corresponding entry as free
+      ((DIR *) dir)->fs = NULL;
+
+      //Leave critical section
+      osReleaseMutex(&fsMutex);
+   }
+}
+