diff --git a/miosix/Makefile b/miosix/Makefile index 909c58f4630e10feed1268a4f5c6254c8b8f13d0..344ece19bbab8a130d8c0be8f50400266b26feba 100644 --- a/miosix/Makefile +++ b/miosix/Makefile @@ -24,7 +24,6 @@ filesystem/stringpart.cpp \ filesystem/console/console_device.cpp \ filesystem/mountpointfs/mountpointfs.cpp \ filesystem/devfs/devfs.cpp \ -filesystem/devfs/base_files.cpp \ filesystem/fat32/fat32.cpp \ filesystem/fat32/ff.cpp \ filesystem/fat32/diskio.cpp \ diff --git a/miosix/_doc/textdoc/Changelog.txt b/miosix/_doc/textdoc/Changelog.txt index 1f053cd16672c199bb7c116007f700360efd4b2e..12e8a17dcffe64ce61cf520d6883acf75a4ba214 100644 --- a/miosix/_doc/textdoc/Changelog.txt +++ b/miosix/_doc/textdoc/Changelog.txt @@ -1,5 +1,15 @@ Changelog for Miosix np embedded OS +- Changed Fat32Fs so that reads and writes are directed to a generic file + instead of to the disk interface. Added temporary DiskAdapter class to + maintain compatibility with the old interface until bsps are upgraded. +- Major rework and simplification of the DevFs infrastructure. Getting rid of + stateless device files. All devices are now stateful, and to make a device you + only have to subclass Device and implement readBlock()/writeBlock()/ioctl() +- Removed sync() syscall, replaced by ioctl() +- Added ioctl() syscall, and miosix/filesystem/ioctl.h with list of IOCTLs +- Removed reliance on global variable for FatFs, to have allow mounting more + than one independent Fat32 filesystem. - First working but inefficient unicode support for fat32 - Fixed a bug in fat32 directory listing causing file names to be skipped when listing large directories. diff --git a/miosix/filesystem/console/console_device.cpp b/miosix/filesystem/console/console_device.cpp index 4e081e33013a9206b1005531b8aeda7b7c341886..99b7d4877ca8c65a544d67fd1c3340dcc93a14d9 100644 --- a/miosix/filesystem/console/console_device.cpp +++ b/miosix/filesystem/console/console_device.cpp @@ -200,7 +200,11 @@ int TerminalDevice::fstat(struct stat *pstat) const int TerminalDevice::isatty() const { return device->isatty(); } -int TerminalDevice::sync() { return device->sync(); } +int TerminalDevice::ioctl(int cmd, void *arg) +{ + //TODO: trap ioctl to change terminal settings + return device->ioctl(cmd,arg); +} // // class DefaultConsole diff --git a/miosix/filesystem/console/console_device.h b/miosix/filesystem/console/console_device.h index 5624d68777580a0784653b781c258d1b40222b1d..8cb8b5d39629429154b79cb980a68b0559e38a38 100644 --- a/miosix/filesystem/console/console_device.h +++ b/miosix/filesystem/console/console_device.h @@ -154,10 +154,12 @@ public: virtual int isatty() const; /** - * Wait until all I/O operations have completed on this file. - * \return 0 on success, or a negative number in case of errors + * Perform various operations on a file descriptor + * \param cmd specifies the operation to perform + * \param arg optional argument that some operation require + * \return the exact return value depends on CMD, -1 is returned on error */ - virtual int sync(); + virtual int ioctl(int cmd, void *arg); /** * Enables or disables echo of commands on the terminal diff --git a/miosix/filesystem/devfs/base_files.h b/miosix/filesystem/devfs/base_files.h deleted file mode 100644 index e887a07f94829da2a7539bcf961197447d958e70..0000000000000000000000000000000000000000 --- a/miosix/filesystem/devfs/base_files.h +++ /dev/null @@ -1,183 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2013 by Terraneo Federico * - * * - * 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. * - * * - * As a special exception, if other files instantiate templates or use * - * macros or inline functions from this file, or you compile this file * - * and link it with other works to produce a work based on this file, * - * this file does not by itself cause the resulting work to be covered * - * by the GNU General Public License. However the source code for this * - * file must still be made available in accordance with the GNU General * - * Public License. This exception does not invalidate any other reasons * - * why a work based on this file might be covered by the GNU General * - * Public License. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, see <http://www.gnu.org/licenses/> * - ***************************************************************************/ - -#ifndef BASE_FILES_H -#define BASE_FILES_H - -#include "devfs.h" -#include "config/miosix_settings.h" - -#ifdef WITH_DEVFS - -namespace miosix { - -/** - * A file where write operations do nothing at all - */ -class NullFile : public StatelessDeviceFile -{ -public: - /** - * Constructor - * \param parent the filesystem to which this file belongs - */ - NullFile() {} - - /** - * Write data to the file, if the file supports writing. - * \param data the data to write - * \param len the number of bytes to write - * \return the number of written characters, or a negative number in case - * of errors - */ - virtual ssize_t write(const void *data, size_t len); - - /** - * Read data from the file, if the file supports reading. - * \param data buffer to store read data - * \param len the number of bytes to read - * \return the number of read characters, or a negative number in case - * of errors - */ - virtual ssize_t read(void *data, size_t len); -}; - -/** - * A file where read operations return zeroed out memory - */ -class ZeroFile : public StatelessDeviceFile -{ -public: - /** - * Constructor - * \param parent the filesystem to which this file belongs - */ - ZeroFile() {} - - /** - * Write data to the file, if the file supports writing. - * \param data the data to write - * \param len the number of bytes to write - * \return the number of written characters, or a negative number in case - * of errors - */ - virtual ssize_t write(const void *data, size_t len); - - /** - * Read data from the file, if the file supports reading. - * \param data buffer to store read data - * \param len the number of bytes to read - * \return the number of read characters, or a negative number in case - * of errors - */ - virtual ssize_t read(void *data, size_t len); -}; - -/** - * A DeviceFileGenerator that produces files like /proc/cpuinfo, with - * a message that can be read by the application. Message is sampled when - * the file is opened. - */ -class MessageFileGenerator : public DeviceFileGenerator, - private IntrusiveRefCountedSharedFromThis<MessageFileGenerator> -{ -public: - /** - * Return an instance of the file type managed by this DeviceFileGenerator - * \param file the file object will be stored here, if the call succeeds - * \param flags file flags (open for reading, writing, ...) - * \param mode file permissions - * \return 0 on success, or a negative number on failure - */ - virtual int open(intrusive_ref_ptr<FileBase>& file, int flags, int mode); - - /** - * Set the returned message - * \param message the new message - */ - void setMessage(std::string message) - { - Lock<FastMutex> l(mutex); - this->message=message; - } - - /** - * \return the current message - */ - std::string getMessage() const - { - Lock<FastMutex> l(mutex); - return message; - } - -private: - /** - * The stateful class which handles reading the message - */ - class MessageFile : public StatefulDeviceFile - { - public: - /** - * Constructor - * \param parent the filesystem to which this file belongs - */ - MessageFile(intrusive_ref_ptr<DeviceFileGenerator> dfg, std::string m) - : StatefulDeviceFile(dfg), message(m), index(0) {} - - /** - * Write data to the file, if the file supports writing. - * \param data the data to write - * \param len the number of bytes to write - * \return the number of written characters, or a negative number in - * case of errors - */ - virtual ssize_t write(const void *data, size_t len); - - /** - * Read data from the file, if the file supports reading. - * \param data buffer to store read data - * \param len the number of bytes to read - * \return the number of read characters, or a negative number in - * case of errors - */ - virtual ssize_t read(void *data, size_t len); - - private: - FastMutex mutex; - std::string message; - int index; - }; - - mutable FastMutex mutex; - std::string message; -}; - -} //namespace miosix - -#endif //WITH_DEVFS - -#endif //BASE_FILES_H diff --git a/miosix/filesystem/devfs/devfs.cpp b/miosix/filesystem/devfs/devfs.cpp index adeb5ea8203ca114eb642ab82245f681539f146e..78c23e6ce9a7a01a619c4cf4682de54ede530cc6 100644 --- a/miosix/filesystem/devfs/devfs.cpp +++ b/miosix/filesystem/devfs/devfs.cpp @@ -29,8 +29,9 @@ #include <string> #include <errno.h> #include <fcntl.h> -#include "base_files.h" #include "filesystem/stringpart.h" +#include "interfaces/disk.h" //FIXME: remove +#include "filesystem/ioctl.h" //FIXME: remove using namespace std; @@ -49,55 +50,274 @@ static void fillStatHelper(struct stat* pstat, unsigned int st_ino, pstat->st_blksize=0; //If zero means file buffer equals to BUFSIZ } -// -// class DeviceFile -// +/** + * This file type is for reading and writing from devices + */ +class DevFsFile : public FileBase +{ +public: + /** + * Constructor + * \param fs pointer to DevFs + * \param dev the device to which this file refers + * \param seekable true if the device is seekable + */ + DevFsFile(intrusive_ref_ptr<FilesystemBase> fs, + intrusive_ref_ptr<Device> dev, bool seekable) : FileBase(fs), + dev(dev), seekPoint(seekable ? 0 : -1) {} + + /** + * Write data to the file, if the file supports writing. + * \param data the data to write + * \param len the number of bytes to write + * \return the number of written characters, or a negative number in + * case of errors + */ + virtual ssize_t write(const void *data, size_t len); + + /** + * Read data from the file, if the file supports reading. + * \param data buffer to store read data + * \param len the number of bytes to read + * \return the number of read characters, or a negative number in + * case of errors + */ + virtual ssize_t read(void *data, size_t len); + + /** + * Move file pointer, if the file supports random-access. + * \param pos offset to sum to the beginning of the file, current position + * or end of file, depending on whence + * \param whence SEEK_SET, SEEK_CUR or SEEK_END + * \return the offset from the beginning of the file if the operation + * completed, or a negative number in case of errors + */ + virtual off_t lseek(off_t pos, int whence); + + /** + * Return file information. + * \param pstat pointer to stat struct + * \return 0 on success, or a negative number on failure + */ + virtual int fstat(struct stat *pstat) const; + + /** + * Perform various operations on a file descriptor + * \param cmd specifies the operation to perform + * \param arg optional argument that some operation require + * \return the exact return value depends on CMD, -1 is returned on error + */ + virtual int ioctl(int cmd, void *arg); -off_t DeviceFile::lseek(off_t pos, int whence) +private: + intrusive_ref_ptr<Device> dev; ///< Device file + ssize_t seekPoint; ///< Seek point, or -1 if unseekabble +}; + +ssize_t DevFsFile::write(const void *data, size_t len) { + if(seekPoint>0 && seekPoint+len<0) + len=numeric_limits<size_t>::max()-seekPoint-len; + int result=dev->writeBlock(data,len,seekPoint); + if(result>0 && seekPoint>0) seekPoint+=result; + return result; +} + +ssize_t DevFsFile::read(void *data, size_t len) +{ + if(seekPoint>0 && seekPoint+len<0) + len=numeric_limits<size_t>::max()-seekPoint-len; + int result=dev->readBlock(data,len,seekPoint); + if(result>0 && seekPoint>0) seekPoint+=result; + return result; +} + +off_t DevFsFile::lseek(off_t pos, int whence) +{ + if(seekPoint<0) return -EBADF; //No seek support + + ssize_t newSeekPoint=seekPoint; switch(whence) { - case SEEK_SET: case SEEK_CUR: - case SEEK_END: - return -EBADF; + newSeekPoint+=pos; + break; + case SEEK_SET: + newSeekPoint=pos; + break; default: - return -EINVAL; + return -EINVAL; //TODO: how to implement SEEK_END? } + if(newSeekPoint<0) return -EOVERFLOW; + seekPoint=newSeekPoint; + return seekPoint; } -// -// class StatelessDeviceFile -// +int DevFsFile::fstat(struct stat *pstat) const +{ + return dev->lstat(pstat); +} -int StatelessDeviceFile::fstat(struct stat* pstat) const +int DevFsFile::ioctl(int cmd, void *arg) { - fillStatHelper(pstat,st_ino,st_dev,S_IFCHR | 0755);//crwxr-xr-x - return 0; + return dev->ioctl(cmd,arg); } // -// class StatefulDeviceFile +// class Device // -int StatefulDeviceFile::fstat(struct stat *pstat) const +int Device::open(intrusive_ref_ptr<FileBase>& file, + intrusive_ref_ptr<FilesystemBase> fs, int flags, int mode) +{ + file=intrusive_ref_ptr<FileBase>( + new DevFsFile(fs,shared_from_this(),seekable)); + return 0; +} + +int Device::lstat(struct stat* pstat) const { - pair<unsigned int,short> fi=dfg->getFileInfo(); - fillStatHelper(pstat,fi.first,fi.second,S_IFCHR | 0755);//crwxr-xr-x + mode_t mode=(block ? S_IFBLK : S_IFCHR) | 0750;//brwxr-x--- | crwxr-x--- + fillStatHelper(pstat,st_ino,st_dev,mode); return 0; } +int Device::readBlock(void *buffer, int size, int where) +{ + memset(buffer,0,size); //Act as /dev/zero + return size; +} + +int Device::writeBlock(const void *buffer, int size, int where) +{ + return size; //Act as /dev/null +} + +int Device::ioctl(int cmd, void *arg) +{ + return -ENOTTY; //Means the operation does not apply to this descriptor +} + +Device::~Device() {} + // -// class DeviceFileGenerator +// class DiskAdapter // -int DeviceFileGenerator::lstat(struct stat *pstat) +// FIXME temporary -- begin +DiskAdapter::DiskAdapter() : Device(true,true) +{ + if(Disk::isAvailable()) Disk::init(); +} + +int DiskAdapter::readBlock(void* buffer, int size, int where) +{ + if(Disk::isInitialized()==false) return -EBADF; + if(where % 512 || size % 512) return -EFAULT; + Lock<FastMutex> l(mutex); + if(Disk::read((unsigned char*)buffer,where/512,size/512)) return size; + else return -EFAULT; +} + +int DiskAdapter::writeBlock(const void* buffer, int size, int where) { - fillStatHelper(pstat,st_ino,st_dev,S_IFCHR | 0755);//crwxr-xr-x + if(Disk::isInitialized()==false) return -EBADF; + if(where % 512 || size % 512) return -EFAULT; + Lock<FastMutex> l(mutex); + if(Disk::write((const unsigned char*)buffer,where/512,size/512)) return size; + else return -EFAULT; +} + +int DiskAdapter::ioctl(int cmd, void *arg) +{ + if(cmd!=IOCTL_SYNC) return -ENOTTY; + Lock<FastMutex> l(mutex); + Disk::sync(); return 0; } +// FIXME temporary -- begin + +/** + * Directory class for DevFs + */ +class DevFsDirectory : public DirectoryBase +{ +public: + /** + * \param parent parent filesystem + * \param mutex mutex to lock when accessing the file map + * \param files file map + * \param currentInode inode of the directory we're listing + * \param parentInode inode of the parent directory + */ + DevFsDirectory(intrusive_ref_ptr<FilesystemBase> parent, + FastMutex& mutex, + map<StringPart,intrusive_ref_ptr<Device> >& files, + int currentInode, int parentInode) + : DirectoryBase(parent), mutex(mutex), files(files), + currentInode(currentInode), parentInode(parentInode), + first(true), last(false) + { + Lock<FastMutex> l(mutex); + if(files.empty()==false) currentItem=files.begin()->first.c_str(); + } -DeviceFileGenerator::~DeviceFileGenerator() {} + /** + * Also directories can be opened as files. In this case, this system + * call allows to retrieve directory entries. + * \param dp pointer to a memory buffer where one or more struct dirent + * will be placed. dp must be four words aligned. + * \param len memory buffer size. + * \return the number of bytes read on success, or a negative number on + * failure. + */ + virtual int getdents(void *dp, int len); + +private: + FastMutex& mutex; ///< Mutex of parent class + map<StringPart,intrusive_ref_ptr<Device> >& files; ///< Directory entries + string currentItem; ///< First unhandled item in directory + int currentInode,parentInode; ///< Inodes of . and .. + + bool first; ///< True if first time getdents is called + bool last; ///< True if directory has ended +}; + +int DevFsDirectory::getdents(void *dp, int len) +{ + if(len<minimumBufferSize) return -EINVAL; + if(last) return 0; + + Lock<FastMutex> l(mutex); + char *begin=reinterpret_cast<char*>(dp); + char *buffer=begin; + char *end=buffer+len; + if(first) + { + first=false; + addDefaultEntries(&buffer,currentInode,parentInode); + } + if(currentItem.empty()==false) + { + map<StringPart,intrusive_ref_ptr<Device> >::iterator it; + it=files.find(StringPart(currentItem)); + //Someone deleted the exact directory entry we had saved (unlikely) + if(it==files.end()) return -EBADF; + for(;it!=files.end();++it) + { + struct stat st; + it->second->lstat(&st); + if(addEntry(&buffer,end,st.st_ino,st.st_mode>>12,it->first)>0) + continue; + //Buffer finished + currentItem=it->first.c_str(); + return buffer-begin; + } + } + addTerminatingEntry(&buffer,end); + last=true; + return buffer-begin; +} // // class DevFs @@ -105,24 +325,28 @@ DeviceFileGenerator::~DeviceFileGenerator() {} DevFs::DevFs() : mutex(FastMutex::RECURSIVE), inodeCount(rootDirInode+1) { - //This will increase openFilesCount to 1, because we don't have an easy way - //to keep track of open files, due to DeviceFileWrapper having stateless - //device files open also when no process has it open, and because having - //the DeviceFile's parent pointer point to the DevFs would generate a loop - //of refcounted pointers with stateless files. Simply, we don't recommend - //umounting DevFs, and to do so we leave openFilesCount permanently to 1, - //so that only a forced umount can umount it. - newFileOpened(); - - addDeviceFile("null",intrusive_ref_ptr<StatelessDeviceFile>(new NullFile)); - addDeviceFile("zero",intrusive_ref_ptr<StatelessDeviceFile>(new ZeroFile)); + addDevice("null",intrusive_ref_ptr<Device>(new Device)); + addDevice("zero",intrusive_ref_ptr<Device>(new Device)); +} + +bool DevFs::addDevice(const char *name, intrusive_ref_ptr<Device> dev) +{ + if(name==0 || name[0]=='\0') return false; + int len=strlen(name); + for(int i=0;i<len;i++) if(name[i]=='/') return false; + Lock<FastMutex> l(mutex); + bool result=files.insert(make_pair(StringPart(name),dev)).second; + //Assign inode to the file + if(result) dev->setFileInfo(atomicAddExchange(&inodeCount,1),filesystemId); + return result; } bool DevFs::remove(const char* name) { if(name==0 || name[0]=='\0') return false; Lock<FastMutex> l(mutex); - map<StringPart,DeviceFileWrapper>::iterator it=files.find(StringPart(name)); + map<StringPart,intrusive_ref_ptr<Device> >::iterator it; + it=files.find(StringPart(name)); if(it==files.end()) return false; files.erase(StringPart(name)); return true; @@ -140,9 +364,9 @@ int DevFs::open(intrusive_ref_ptr<FileBase>& file, StringPart& name, mutex,files,rootDirInode,parentFsMountpointInode)); return 0; } - map<StringPart,DeviceFileWrapper>::iterator it=files.find(name); + map<StringPart,intrusive_ref_ptr<Device> >::iterator it=files.find(name); if(it==files.end()) return -ENOENT; - return it->second.open(file,flags,mode); + return it->second->open(file,shared_from_this(),flags,mode); } int DevFs::lstat(StringPart& name, struct stat *pstat) @@ -153,9 +377,9 @@ int DevFs::lstat(StringPart& name, struct stat *pstat) fillStatHelper(pstat,rootDirInode,filesystemId,S_IFDIR | 0755);//drwxr-xr-x return 0; } - map<StringPart,DeviceFileWrapper>::iterator it=files.find(name); + map<StringPart,intrusive_ref_ptr<Device> >::iterator it=files.find(name); if(it==files.end()) return -ENOENT; - return it->second.lstat(pstat); + return it->second->lstat(pstat); } int DevFs::unlink(StringPart& name) @@ -168,7 +392,7 @@ int DevFs::unlink(StringPart& name) int DevFs::rename(StringPart& oldName, StringPart& newName) { Lock<FastMutex> l(mutex); - map<StringPart,DeviceFileWrapper>::iterator it=files.find(oldName); + map<StringPart,intrusive_ref_ptr<Device> >::iterator it=files.find(oldName); if(it==files.end()) return -ENOENT; for(unsigned int i=0;i<newName.length();i++) if(newName[i]=='/') @@ -189,58 +413,6 @@ int DevFs::rmdir(StringPart& name) return -EACCES; // No directories support in DevFs yet } -bool DevFs::addDeviceFile(const char *name, DeviceFileWrapper dfw) -{ - if(name==0 || name[0]=='\0') return false; - int len=strlen(name); - for(int i=0;i<len;i++) if(name[i]=='/') return false; - Lock<FastMutex> l(mutex); - bool result=files.insert(make_pair(StringPart(name),dfw)).second; - //Assign inode to the file - if(result) dfw.setFileInfo(atomicAddExchange(&inodeCount,1),filesystemId); - return result; -} - -// -// class DevFs::DevFsDirctory -// - -int DevFs::DevFsDirectory::getdents(void *dp, int len) -{ - if(len<minimumBufferSize) return -EINVAL; - if(last) return 0; - - Lock<FastMutex> l(mutex); - char *begin=reinterpret_cast<char*>(dp); - char *buffer=begin; - char *end=buffer+len; - if(first) - { - first=false; - addDefaultEntries(&buffer,currentInode,parentInode); - } - if(currentItem.empty()==false) - { - map<StringPart,DeviceFileWrapper>::iterator it; - it=files.find(StringPart(currentItem)); - //Someone deleted the exact directory entry we had saved (unlikely) - if(it==files.end()) return -EBADF; - for(;it!=files.end();++it) - { - struct stat st; - it->second.lstat(&st); - if(addEntry(&buffer,end,st.st_ino,st.st_mode>>12,it->first)>0) - continue; - //Buffer finished - currentItem=it->first.c_str(); - return buffer-begin; - } - } - addTerminatingEntry(&buffer,end); - last=true; - return buffer-begin; -} - } //namespace miosix #endif //WITH_DEVFS diff --git a/miosix/filesystem/devfs/devfs.h b/miosix/filesystem/devfs/devfs.h index 228a799cf1b8444b44a3394098b84f95a09325d6..dd73b7a2f04339c2e7b2a76c135b098858c54317 100644 --- a/miosix/filesystem/devfs/devfs.h +++ b/miosix/filesystem/devfs/devfs.h @@ -38,123 +38,49 @@ namespace miosix { -//Forward decls -class DeviceFileGenerator; - -/** - * All device files that are meant to be attached to DevFs must derive from this - * class, but not directly, either through StatefulDeviceFile or StatelessDeviceFile - */ -class DeviceFile : public FileBase -{ -public: - /** - * Constructor - */ - DeviceFile() : FileBase(intrusive_ref_ptr<FilesystemBase>()) {} - - /** - * Default implementation that returns an error code, as most device file - * are not seekable. - */ - virtual off_t lseek(off_t pos, int whence); -}; - /** - * All stateless device files must derive from this class - */ -class StatelessDeviceFile : public DeviceFile -{ -public: - /** - * Constructor - */ - StatelessDeviceFile() : st_ino(0), st_dev(0) {} - - /** - * Return file information. - * \param pstat pointer to stat struct - * \return 0 on success, or a negative number on failure - */ - virtual int fstat(struct stat *pstat) const; - - /** - * Set the device file's information, inode number and device file. - * \param st_ino device file inode - * \param st_dev device file dvice number - */ - void setFileInfo(unsigned int st_ino, short st_dev) - { - this->st_ino=st_ino; - this->st_dev=st_dev; - } - -protected: - unsigned int st_ino; ///< inode of device file - short st_dev; ///< device (unique id of the filesystem) of device file -}; - -/** - * All stateful device files must derive from this class, and in addition - * must subclass DeviceFileGenerator to generate instances of these files - */ -class StatefulDeviceFile : public DeviceFile -{ -public: - /** - * Constructor - * \param dfg the DeviceFileGenerator to which this file belongs - */ - explicit StatefulDeviceFile(intrusive_ref_ptr<DeviceFileGenerator> dfg) - : dfg(dfg) {} - - /** - * Return file information. - * \param pstat pointer to stat struct - * \return 0 on success, or a negative number on failure - */ - virtual int fstat(struct stat *pstat) const; - -protected: - intrusive_ref_ptr<DeviceFileGenerator> dfg; -}; - -/** - * Instances of this class take care of producing instances of a specific - * stateful device file inside DevFs. Stateful device files look like - * /proc/cpuinfo. They have a state represented by the point at which the - * process has arrived reading the file, and as such every time the device - * file is opened, a new instance has to be returned. - * To support that, the driver developer has to subclass DeviceFileGenerator - * and StatefulDeviceFile to implement the desired logic. Stateless device - * files are instead passed directly to DevFs and every open returns the same - * file instance. + * Instances of this class are devices inside DevFs. When open is called, a + * DevFsFile is returned, which has its own seek point so that multiple files + * can be opened on the same device retaining an unique seek point. A DevFsFile + * then calls readBlock() and writeBlock() on this class. These functions have a + * third argument which is the seek point, making them stateless. + * + * Individual devices must subclass Device and reimplement readBlock(), + * writeBlock() and ioctl() as needed. A mutex may be required as multiple + * concurrent readBlock(), writeBlock() and ioctl() can occur. + * * Classes of this type are reference counted, must be allocated on the heap * and managed through intrusive_ref_ptr<FileBase> */ -class DeviceFileGenerator : public IntrusiveRefCounted +class Device : public IntrusiveRefCounted, + public IntrusiveRefCountedSharedFromThis<Device> { public: /** - * Constructor. + * Constructor + * \param seekable if true, device is seekable + * \param block if true, it is a block device */ - DeviceFileGenerator() {} - + Device(bool seekable=false, bool block=false) + : seekable(seekable), block(block) {} + /** * Return an instance of the file type managed by this DeviceFileGenerator * \param file the file object will be stored here, if the call succeeds + * \param fs pointer to the DevFs * \param flags file flags (open for reading, writing, ...) * \param mode file permissions * \return 0 on success, or a negative number on failure */ - virtual int open(intrusive_ref_ptr<FileBase>& file, int flags, int mode)=0; + int open(intrusive_ref_ptr<FileBase>& file, + intrusive_ref_ptr<FilesystemBase> fs, int flags, int mode); /** * Obtain information for the file type managed by this DeviceFileGenerator * \param pstat file information is stored here * \return 0 on success, or a negative number on failure */ - virtual int lstat(struct stat *pstat); + int lstat(struct stat *pstat) const; /** * \internal @@ -167,25 +93,55 @@ public: } /** - * \return a pair with the device file's inode and device numbers (fs id) + * Read a block of data + * \param buffer buffer where read data will be stored + * \param size buffer size + * \param where where to read from + * \return number of bytes read or a negative number on failure */ - std::pair<unsigned int,short> getFileInfo() const - { - return std::make_pair(st_ino,st_dev); - } + virtual int readBlock(void *buffer, int size, int where); /** - * Destructor + * Write a block of data + * \param buffer buffer where take data to write + * \param size buffer size + * \param where where to write to + * \return number of bytes written or a negative number on failure + */ + virtual int writeBlock(const void *buffer, int size, int where); + + /** + * Performs device-specific operations + * \param cmd specifies the operation to perform + * \param arg optional argument that some operation require + * \return the exact return value depends on CMD, -1 is returned on error */ - virtual ~DeviceFileGenerator(); + virtual int ioctl(int cmd, void *arg); + /** + * Destructor + */ + virtual ~Device(); + protected: unsigned int st_ino; ///< inode of device file - short st_dev; ///< device (unique id of the filesystem) of device file - + short st_dev; ///< device (unique id of the filesystem) of device file + const bool seekable; ///< If true, device is seekable + const bool block; ///< If true, it is a block device +}; + +/** + * FIXME remove this when removing Console interface! + */ +class DiskAdapter : public Device +{ +public: + DiskAdapter(); + virtual int readBlock(void *buffer, int size, int where); + virtual int writeBlock(const void *buffer, int size, int where); + virtual int ioctl(int cmd, void *arg); private: - DeviceFileGenerator(const DeviceFileGenerator&); - DeviceFileGenerator& operator=(const DeviceFileGenerator&); + FastMutex mutex; }; /** @@ -212,30 +168,15 @@ public: DevFs(); /** - * Add a stateless device file to DevFs + * Add a device file to DevFs * \param name File name, must not start with a slash * \param df Device file. Every open() call will return the same file * \return true if the file was successfully added */ - bool addDeviceFile(const char *name, intrusive_ref_ptr<StatelessDeviceFile> df) - { - return addDeviceFile(name,DeviceFileWrapper(df)); - } - - /** - * Add a stateful device file to DevFs - * \param name File name, must not start with a slash - * \param dfg Device file generator - * \return true if the file was successfully added - */ - bool addDeviceFileGenerator(const char *name, - intrusive_ref_ptr<DeviceFileGenerator> dfg) - { - return addDeviceFile(name,DeviceFileWrapper(dfg)); - } + bool addDevice(const char *name, intrusive_ref_ptr<Device> dev); /** - * Remove a device file. This prevents the file from being opened again, + * Remove a device. This prevents the device from being opened again, * but if at the time this member function is called the file is already * opened, it won't be deallocated till the application closes it, thanks * to the reference counting scheme. @@ -296,127 +237,9 @@ public: virtual int rmdir(StringPart& name); private: - //Forward decl - class DeviceFileWrapper; - - /** - * Add a file to the DevFs - * \param name device name - * \param dfw DeviceFileWrapper - * \return true on success, false on failure - */ - bool addDeviceFile(const char *name, DeviceFileWrapper dfw); - - /** - * Wrapper class for accessing device files - */ - class DeviceFileWrapper - { - public: - /** - * Constructor with DeviceFileGenerator - * \param dfg the DeviceFileGenerator that will be used to produce - * device files - */ - explicit DeviceFileWrapper(intrusive_ref_ptr<DeviceFileGenerator> dfg) - : dfg(dfg), df() {} - - /** - * Constructor with DeviceFile - * \param df the device file that is returned every time the file is - * opened - */ - explicit DeviceFileWrapper(intrusive_ref_ptr<StatelessDeviceFile> df) - : dfg(), df(df) {} - - /** - * Return an instance of the file - * \param file the file object will be stored here, if the call succeeds - * \param flags file flags (open for reading, writing, ...) - * \param mode file permissions - * \return 0 on success, or a negative number on failure - */ - int open(intrusive_ref_ptr<FileBase>& file, int flags, int mode) - { - if(dfg) return dfg->open(file,flags,mode); - file=df; - return 0; - } - - /** - * Obtain information for the file - * \param pstat file information is stored here - * \return 0 on success, or a negative number on failure - */ - int lstat(struct stat *pstat) - { - if(dfg) return dfg->lstat(pstat); - else return df->fstat(pstat); - } - - /** - * \internal - * Called be DevFs to assign a device and inode to the DeviceFileGenerator - */ - void setFileInfo(unsigned int st_ino, short st_dev) - { - if(dfg) dfg->setFileInfo(st_ino,st_dev); - else df->setFileInfo(st_ino,st_dev); - } - - private: - //One of these is always null - intrusive_ref_ptr<DeviceFileGenerator> dfg; - intrusive_ref_ptr<StatelessDeviceFile> df; - }; - - /** - * Directory class for DevFs - */ - class DevFsDirectory : public DirectoryBase - { - public: - /** - * \param parent parent filesystem - * \param mutex mustex to lock when accessing the file map - * \param files file map - * \param currentInode inode of the directory we're listing - * \param parentInode inode of the parent directory - */ - DevFsDirectory(intrusive_ref_ptr<FilesystemBase> parent, - FastMutex& mutex, std::map<StringPart,DeviceFileWrapper>& files, - int currentInode, int parentInode) - : DirectoryBase(parent), mutex(mutex), files(files), - currentInode(currentInode), parentInode(parentInode), - first(true), last(false) - { - Lock<FastMutex> l(mutex); - if(files.empty()==false) currentItem=files.begin()->first.c_str(); - } - - /** - * Also directories can be opened as files. In this case, this system - * call allows to retrieve directory entries. - * \param dp pointer to a memory buffer where one or more struct dirent - * will be placed. dp must be four words aligned. - * \param len memory buffer size. - * \return the number of bytes read on success, or a negative number on - * failure. - */ - virtual int getdents(void *dp, int len); - - private: - FastMutex& mutex; ///< Mutex of parent class - std::map<StringPart,DeviceFileWrapper>& files; ///< Directory entries - std::string currentItem; ///< First unhandled item in directory - int currentInode,parentInode; ///< Inodes of . and .. - - bool first; ///< True if first time getdents is called - bool last; ///< True if directory has ended - }; FastMutex mutex; - std::map<StringPart,DeviceFileWrapper> files; + std::map<StringPart,intrusive_ref_ptr<Device> > files; int inodeCount; static const int rootDirInode=1; }; diff --git a/miosix/filesystem/fat32/diskio.cpp b/miosix/filesystem/fat32/diskio.cpp index bdf7dc686e9d98eaf1af51055284edbcda7b3d81..bc2f96982cc470f5d2d5d196ff47cb6a620d79e0 100644 --- a/miosix/filesystem/fat32/diskio.cpp +++ b/miosix/filesystem/fat32/diskio.cpp @@ -4,7 +4,7 @@ */ #include "diskio.h" -#include "interfaces/disk.h" +#include "filesystem/ioctl.h" using namespace miosix; @@ -12,49 +12,46 @@ using namespace miosix; // extern "C" { // #endif -/** - * \internal - * Initializes drive. - */ -DSTATUS disk_initialize ( - BYTE drv /* Physical drive nmuber (0..) */ -) -{ - if(drv!=0) return STA_NOINIT;//Only drive 0 is supported - if(Disk::isAvailable()==false) return STA_NODISK; - Disk::init(); - if(Disk::isInitialized()) return RES_OK; - else return STA_NOINIT; -} +///** +// * \internal +// * Initializes drive. +// */ +//DSTATUS disk_initialize ( +// intrusive_ref_ptr<FileBase> pdrv /* Physical drive nmuber (0..) */ +//) +//{ +// if(Disk::isAvailable()==false) return STA_NODISK; +// Disk::init(); +// if(Disk::isInitialized()) return RES_OK; +// else return STA_NOINIT; +//} -/** - * \internal - * Return status of drive. - */ -DSTATUS disk_status ( - BYTE drv /* Physical drive nmuber (0..) */ -) -{ - if(drv!=0) return STA_NOINIT;//Only drive 0 is supported - if(Disk::isInitialized()) return RES_OK; - else return STA_NOINIT; -} +///** +// * \internal +// * Return status of drive. +// */ +//DSTATUS disk_status ( +// intrusive_ref_ptr<FileBase> pdrv /* Physical drive nmuber (0..) */ +//) +//{ +// if(Disk::isInitialized()) return RES_OK; +// else return STA_NOINIT; +//} /** * \internal * Read one or more sectors from drive */ DRESULT disk_read ( - BYTE drv, /* Physical drive nmuber (0..) */ + intrusive_ref_ptr<FileBase> pdrv, /* Physical drive nmuber (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to read (1..255) */ ) { - if(drv!=0 || count==0) return RES_PARERR; - if(Disk::isInitialized()==false) return RES_NOTRDY; - if(Disk::read(buff,sector,count)) return RES_OK; - else return RES_ERROR; + if(pdrv->lseek(sector*512,SEEK_SET)<0) return RES_ERROR; + if(pdrv->read(buff,count*512)!=count*512) return RES_ERROR; + return RES_OK; } /** @@ -62,16 +59,15 @@ DRESULT disk_read ( * Write one or more sectors to drive */ DRESULT disk_write ( - BYTE drv, /* Physical drive nmuber (0..) */ + intrusive_ref_ptr<FileBase> pdrv, /* Physical drive nmuber (0..) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ UINT count /* Number of sectors to write (1..255) */ ) { - if(drv!=0 || count==0) return RES_PARERR; - if(Disk::isInitialized()==false) return RES_NOTRDY; - if(Disk::write(buff,sector,count)) return RES_OK; - else return RES_ERROR; + if(pdrv->lseek(sector*512,SEEK_SET)<0) return RES_ERROR; + if(pdrv->write(buff,count*512)!=count*512) return RES_ERROR; + return RES_OK; } /** @@ -79,17 +75,15 @@ DRESULT disk_write ( * To perform disk functions other thar read/write */ DRESULT disk_ioctl ( - BYTE drv, /* Physical drive nmuber (0..) */ + intrusive_ref_ptr<FileBase> pdrv, /* Physical drive nmuber (0..) */ BYTE ctrl, /* Control code */ void *buff /* Buffer to send/receive control data */ ) { - if(drv!=0) return RES_PARERR; - if(Disk::isInitialized()==false) return RES_NOTRDY; switch(ctrl) { case CTRL_SYNC: - if(Disk::sync()) return RES_OK; else return RES_ERROR; + if(pdrv->ioctl(IOCTL_SYNC,0)==0) return RES_OK; else return RES_ERROR; case GET_SECTOR_COUNT: return RES_ERROR; //unimplemented, so f_mkfs() does not work case GET_BLOCK_SIZE: diff --git a/miosix/filesystem/fat32/diskio.h b/miosix/filesystem/fat32/diskio.h index 97638aa308464eee05bbba280804f90b0f391e21..c8f4e9cb8ea98ccbd92523cab3737f6f7506c496 100644 --- a/miosix/filesystem/fat32/diskio.h +++ b/miosix/filesystem/fat32/diskio.h @@ -5,14 +5,15 @@ #ifndef _DISKIO_DEFINED #define _DISKIO_DEFINED -#ifdef __cplusplus -extern "C" { -#endif +//#ifdef __cplusplus +//extern "C" { +//#endif #define _USE_WRITE 1 /* 1: Enable disk_write function */ #define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ #include "integer.h" +#include <filesystem/file.h> /* Status of Disk Functions */ @@ -32,11 +33,14 @@ typedef enum { /* Prototypes for disk control functions */ -DSTATUS disk_initialize (BYTE pdrv); -DSTATUS disk_status (BYTE pdrv); -DRESULT disk_read (BYTE pdrv, BYTE*buff, DWORD sector, UINT count); -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); +DSTATUS disk_initialize (miosix::intrusive_ref_ptr<miosix::FileBase> pdrv); +DSTATUS disk_status (miosix::intrusive_ref_ptr<miosix::FileBase> pdrv); +DRESULT disk_read (miosix::intrusive_ref_ptr<miosix::FileBase> pdrv, + BYTE*buff, DWORD sector, UINT count); +DRESULT disk_write (miosix::intrusive_ref_ptr<miosix::FileBase> pdrv, + const BYTE* buff, DWORD sector, UINT count); +DRESULT disk_ioctl (miosix::intrusive_ref_ptr<miosix::FileBase> pdrv, + BYTE cmd, void* buff); /* Disk Status Bits (DSTATUS) */ @@ -81,8 +85,8 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); #define CT_BLOCK 0x08 /* Block addressing */ -#ifdef __cplusplus -} -#endif +//#ifdef __cplusplus +//} +//#endif #endif diff --git a/miosix/filesystem/fat32/fat32.cpp b/miosix/filesystem/fat32/fat32.cpp index eeee7fb47d45cd38661007616ba67b2fd65e286c..b62a664300f02a22b13c91098287edc113330fca 100644 --- a/miosix/filesystem/fat32/fat32.cpp +++ b/miosix/filesystem/fat32/fat32.cpp @@ -36,7 +36,7 @@ #include <string> #include <cstdio> #include "filesystem/stringpart.h" -#include "interfaces/disk.h" +#include "filesystem/ioctl.h" #include "util/unicode.h" using namespace std; @@ -225,10 +225,12 @@ public: virtual int fstat(struct stat *pstat) const; /** - * Wait until all I/O operations have completed on this file. - * \return 0 on success, or a negative number in case of errors + * Perform various operations on a file descriptor + * \param cmd specifies the operation to perform + * \param arg optional argument that some operation require + * \return the exact return value depends on CMD, -1 is returned on error */ - virtual int sync(); + virtual int ioctl(int cmd, void *arg); /** * \return the FatFs FIL object @@ -315,8 +317,9 @@ int Fat32File::fstat(struct stat *pstat) const return 0; } -int Fat32File::sync() +int Fat32File::ioctl(int cmd, void *arg) { + if(cmd!=IOCTL_SYNC) return -ENOTTY; Lock<FastMutex> l(mutex); return translateError(f_sync(&file)); } @@ -331,9 +334,10 @@ Fat32File::~Fat32File() // class Fat32Fs // -Fat32Fs::Fat32Fs() : mutex(FastMutex::RECURSIVE), failed(true) +Fat32Fs::Fat32Fs(intrusive_ref_ptr<FileBase> disk) + : mutex(FastMutex::RECURSIVE), failed(true) { - if(!Disk::isAvailable()) return; + filesystem.drv=disk; failed=f_mount(&filesystem,1,false)!=FR_OK; } @@ -473,7 +477,8 @@ Fat32Fs::~Fat32Fs() { if(failed) return; f_mount(&filesystem,0,true); //TODO: what to do with error code? - Disk::sync(); + filesystem.drv->ioctl(IOCTL_SYNC,0); + filesystem.drv.reset(); } int Fat32Fs::unlinkRmdirHelper(StringPart& name, bool delDir) diff --git a/miosix/filesystem/fat32/fat32.h b/miosix/filesystem/fat32/fat32.h index ba365c1851007c2de5e1ba4d5775af31b77983ac..8c66c1178218c8544f7ab4a25b1b2753be9394b2 100644 --- a/miosix/filesystem/fat32/fat32.h +++ b/miosix/filesystem/fat32/fat32.h @@ -43,7 +43,7 @@ public: /** * Constructor */ - Fat32Fs(); + Fat32Fs(intrusive_ref_ptr<FileBase> disk); /** * Open a file diff --git a/miosix/filesystem/fat32/ff.cpp b/miosix/filesystem/fat32/ff.cpp index 00a287b0fb232e66f62b62689a55c7b7da74b648..57fb02fbf4612741b922b1aff03d631d4ee7fe99 100644 --- a/miosix/filesystem/fat32/ff.cpp +++ b/miosix/filesystem/fat32/ff.cpp @@ -2192,7 +2192,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ //*rfs = fs; /* Return pointer to the file system object */ if (fs->fs_type) { /* If the volume has been mounted */ - stat = disk_status(fs->drv); + stat = RES_OK;//disk_status(fs->drv); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ return FR_WRITE_PROTECTED; @@ -2204,8 +2204,8 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ fs->fs_type = 0; /* Clear the file system object */ - fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize the physical drive */ + //fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = RES_OK;//disk_initialize(fs->drv); /* Initialize the physical drive */ if (stat & STA_NOINIT) /* Check if the initialization succeeded */ return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ @@ -2344,8 +2344,8 @@ FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ ENTER_FF(fil->fs); /* Lock file system */ - if (disk_status(fil->fs->drv) & STA_NOINIT) - return FR_NOT_READY; + //if (disk_status(fil->fs->drv) & STA_NOINIT) + // return FR_NOT_READY; return FR_OK; } @@ -4027,7 +4027,7 @@ FRESULT f_mkfs ( part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ /* Get disk statics */ - stat = disk_initialize(pdrv); + stat = RES_OK;//disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; #if _MAX_SS != 512 /* Get disk sector size */ @@ -4254,7 +4254,7 @@ FRESULT f_fdisk ( DWORD sz_disk, sz_part, s_part; - stat = disk_initialize(pdrv); + stat = RES_OK;//disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; diff --git a/miosix/filesystem/fat32/ff.h b/miosix/filesystem/fat32/ff.h index 98276241b17dbe81838fab335951d238f6d723a7..0e3a4fc9ace7dc2c4addb36072222f0ab15baadc 100644 --- a/miosix/filesystem/fat32/ff.h +++ b/miosix/filesystem/fat32/ff.h @@ -21,6 +21,8 @@ //extern "C" { //#endif +#include <filesystem/file.h> + #include "integer.h" /* Basic integer types */ #include "ffconf.h" /* FatFs configuration options */ @@ -90,7 +92,7 @@ typedef struct { struct FATFS { BYTE fs_type; /* FAT sub-type (0:Not mounted) */ - BYTE drv; /* Physical drive number */ + //BYTE drv; /* Physical drive number */ BYTE csize; /* Sectors per cluster (1,2,4...128) */ BYTE n_fats; /* Number of FAT copies (1 or 2) */ BYTE wflag; /* win[] flag (b0:dirty) */ @@ -117,13 +119,14 @@ struct FATFS { DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ DWORD database; /* Data start sector */ DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ + BYTE win[_MAX_SS] __attribute__((aligned(4))); /* Disk access window for Directory, FAT (and file data at tiny cfg) */ #if _USE_LFN == 1 WCHAR LfnBuf[_MAX_LFN+1]; #endif #if _FS_LOCK FILESEM Files[_FS_LOCK];/* Open object lock semaphores */ #endif + miosix::intrusive_ref_ptr<miosix::FileBase> drv; /* drive device */ }; diff --git a/miosix/filesystem/file.cpp b/miosix/filesystem/file.cpp index f3fe4b203d55a08c1bc5d98f9855b953bf88c7c7..ff148a36e4a585b4183832fc9a49ebd6ecc71a3c 100644 --- a/miosix/filesystem/file.cpp +++ b/miosix/filesystem/file.cpp @@ -51,11 +51,6 @@ int FileBase::isatty() const return 0; } -int FileBase::sync() -{ - return 0; -} - int FileBase::fcntl(int cmd, int opt) { //Newlib makes some calls to fcntl, for example in opendir(). CLOEXEC isn't @@ -64,6 +59,11 @@ int FileBase::fcntl(int cmd, int opt) return -EBADF; } +int FileBase::ioctl(int cmd, void *arg) +{ + return -ENOTTY; //Means the operation does not apply to this descriptor +} + int FileBase::getdents(void *dp, int len) { return -EBADF; diff --git a/miosix/filesystem/file.h b/miosix/filesystem/file.h index f677c4219e8ce46a1ddff21f9fe895892ba7f704..495c52a4c5929b7db4227e696d59b801c03a78af 100644 --- a/miosix/filesystem/file.h +++ b/miosix/filesystem/file.h @@ -94,18 +94,20 @@ public: virtual int isatty() const; /** - * Wait until all I/O operations have completed on this file. - * \return 0 on success, or a negative number in case of errors + * Perform various operations on a file descriptor + * \param cmd specifies the operation to perform + * \param opt optional argument that some operation require + * \return the exact return value depends on CMD, -1 is returned on error */ - virtual int sync(); + virtual int fcntl(int cmd, int opt); /** * Perform various operations on a file descriptor * \param cmd specifies the operation to perform - * \param opt optional argument that some operation require + * \param arg optional argument that some operation require * \return the exact return value depends on CMD, -1 is returned on error */ - virtual int fcntl(int cmd, int opt); + virtual int ioctl(int cmd, void *arg); /** * Also directories can be opened as files. In this case, this system call diff --git a/miosix/filesystem/file_access.cpp b/miosix/filesystem/file_access.cpp index 003dc97d28a2602f989d9a607b70939c5c9402d6..ad3ac0f03fcbfadd8e422c34f8ca7e51eb255709 100644 --- a/miosix/filesystem/file_access.cpp +++ b/miosix/filesystem/file_access.cpp @@ -711,8 +711,18 @@ basicFilesystemSetup() //TODO: Move to individual BSPs -- begin bootlog("Mounting Fat32Fs as /sd ... "); StringPart sd("sd"); - intrusive_ref_ptr<Fat32Fs> fat32(new Fat32Fs); - bool fat32failed=fat32->mountFailed(); + + bool fat32failed=false; + intrusive_ref_ptr<Device> da(new DiskAdapter); + intrusive_ref_ptr<FileBase> disk; + if(da->open(disk,intrusive_ref_ptr<FilesystemBase>(0),0,0)<0) fat32failed=true; + + intrusive_ref_ptr<Fat32Fs> fat32; + if(fat32failed==false) + { + fat32=new Fat32Fs(disk); + if(fat32->mountFailed()) fat32failed=true; + } if(fat32failed==false) { fat32failed=rootFs->mkdir(sd,0755)!=0; diff --git a/miosix/filesystem/file_access.h b/miosix/filesystem/file_access.h index abf03306ff59b2f190295a51ee0705b07088b4ea..f3093ee6877045fb4dd6e4b4886ac09950781703 100644 --- a/miosix/filesystem/file_access.h +++ b/miosix/filesystem/file_access.h @@ -186,27 +186,30 @@ public: } /** - * Wait until all I/O operations have completed on this file. - * \return 0 on success, or a negative number in case of errors + * Perform various operations on a file descriptor + * \param cmd specifies the operation to perform + * \param opt optional argument that some operation require + * \return the exact return value depends on CMD, -1 is returned on error */ - int sync(int fd) + int fcntl(int fd, int cmd, int opt) { intrusive_ref_ptr<FileBase> file=getFile(fd); if(!file) return -EBADF; - return file->sync(); + return file->fcntl(cmd,opt); } /** * Perform various operations on a file descriptor * \param cmd specifies the operation to perform - * \param opt optional argument that some operation require + * \param arg optional argument that some operation require * \return the exact return value depends on CMD, -1 is returned on error */ - int fcntl(int fd, int cmd, int opt) + int ioctl(int fd, int cmd, void *arg) { + //arg unchecked here, as some ioctl don't use it intrusive_ref_ptr<FileBase> file=getFile(fd); if(!file) return -EBADF; - return file->fcntl(cmd,opt); + return file->ioctl(cmd,arg); } /** diff --git a/miosix/filesystem/devfs/base_files.cpp b/miosix/filesystem/ioctl.h similarity index 58% rename from miosix/filesystem/devfs/base_files.cpp rename to miosix/filesystem/ioctl.h index 54adf1bceb3aca0509f18ecbd8bacd20f120c689..96a5c40544db4ced516c8b956887be4fb7d1cee7 100644 --- a/miosix/filesystem/devfs/base_files.cpp +++ b/miosix/filesystem/ioctl.h @@ -25,77 +25,12 @@ * along with this program; if not, see <http://www.gnu.org/licenses/> * ***************************************************************************/ -#include "base_files.h" -#include <errno.h> +#ifndef IOCTL_H +#define IOCTL_H -using namespace std; - -#ifdef WITH_DEVFS - -namespace miosix { - -// -// class NullFile -// - -ssize_t NullFile::write(const void *data, size_t len) -{ - return len; -} - -ssize_t NullFile::read(void *data, size_t len) -{ - return -EBADF; -} - -// -// class ZeroFile -// - -ssize_t ZeroFile::write(const void *data, size_t len) -{ - return -EBADF; -} - -ssize_t ZeroFile::read(void *data, size_t len) -{ - memset(data,0,len); - return len; -} - -// -// class MessageFileGenerator -// - -int MessageFileGenerator::open(intrusive_ref_ptr<FileBase>& file, int flags, - int mode) -{ - Lock<FastMutex> l(mutex); - file=intrusive_ref_ptr<FileBase>(new MessageFile(shared_from_this(),message)); - return 0; -} - -// -// class MessageFileGenerator::MessageFile -// - -ssize_t MessageFileGenerator::MessageFile::write(const void* data, size_t len) +enum Ioctl { - return -EBADF; -} - -ssize_t MessageFileGenerator::MessageFile::read(void* data, size_t len) -{ - //The mutex is important, since if two threads call read the resulting race - //condition could cause index>length(), so length()-index becomes a high - //positive value and that could allow dumping part of the kernel memory - Lock<FastMutex> l(mutex); - size_t toRead=min(len,message.length()-index); - memcpy(data,message.c_str()+index,toRead); - index+=toRead; - return toRead; -} - -} //namespace miosix + IOCTL_SYNC=100 +}; -#endif //WITH_DEVFS +#endif //IOCTL_H diff --git a/miosix/stdlib_integration/libc_integration.cpp b/miosix/stdlib_integration/libc_integration.cpp index d0e1cb26e1c23b5f19c7cd5be4adb7aa33df3ad3..2228d1de15a86db82a203b3782fdc6765b3188f3 100644 --- a/miosix/stdlib_integration/libc_integration.cpp +++ b/miosix/stdlib_integration/libc_integration.cpp @@ -571,6 +571,39 @@ int fcntl(int fd, int cmd, ...) return result; } +/** + * \internal + * _ioctl_r, perform operations on a file descriptor + */ +int _ioctl_r(struct _reent *ptr, int fd, int cmd, void *arg) +{ + #ifdef WITH_FILESYSTEM + + #ifndef __NO_EXCEPTIONS + try { + #endif //__NO_EXCEPTIONS + int result=miosix::getFileDescriptorTable().ioctl(fd,cmd,arg); + if(result>=0) return result; + ptr->_errno=-result; + return -1; + #ifndef __NO_EXCEPTIONS + } catch(exception& e) { + ptr->_errno=ENOMEM; + return -1; + } + #endif //__NO_EXCEPTIONS + + #else //WITH_FILESYSTEM + ptr->_errno=ENOENT; + return -1; + #endif //WITH_FILESYSTEM +} + +int ioctl(int fd, int cmd, void *arg) +{ + return _ioctl_r(miosix::CReentrancyAccessor::getReent(),fd,cmd,arg); +} + /** * \internal * _getcwd_r, return current directory diff --git a/miosix_np_2/nbproject/configurations.xml b/miosix_np_2/nbproject/configurations.xml index c52ff5b642406fb0a464aeff4c8201e0350df2b6..c18e868f417a14aa67f1778311517fba0a028d22 100644 --- a/miosix_np_2/nbproject/configurations.xml +++ b/miosix_np_2/nbproject/configurations.xml @@ -309,8 +309,6 @@ <in>console_device.h</in> </df> <df name="devfs"> - <in>base_files.cpp</in> - <in>base_files.h</in> <in>devfs.cpp</in> <in>devfs.h</in> </df> @@ -334,6 +332,7 @@ <in>file.h</in> <in>file_access.cpp</in> <in>file_access.h</in> + <in>ioctl.h</in> <in>stringpart.cpp</in> <in>stringpart.h</in> </df> @@ -1314,16 +1313,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -1366,6 +1355,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -2427,16 +2418,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -2479,6 +2460,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -3542,16 +3525,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -3611,6 +3584,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -4678,16 +4653,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -4730,6 +4695,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -5793,16 +5760,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -5845,6 +5802,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -6908,16 +6867,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -6960,6 +6909,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -8023,16 +7974,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -8075,6 +8016,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -9136,16 +9079,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -9188,6 +9121,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -10249,16 +10184,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -10301,6 +10226,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -11362,16 +11289,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -11414,6 +11331,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -12475,16 +12394,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -12527,6 +12436,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -13588,16 +13499,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -13640,6 +13541,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" @@ -14701,16 +14604,6 @@ tool="3" flavor2="0"> </item> - <item path="../miosix/filesystem/devfs/base_files.cpp" - ex="false" - tool="1" - flavor2="0"> - </item> - <item path="../miosix/filesystem/devfs/base_files.h" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../miosix/filesystem/devfs/devfs.cpp" ex="false" tool="1" @@ -14753,6 +14646,8 @@ </item> <item path="../miosix/filesystem/file_access.h" ex="false" tool="3" flavor2="0"> </item> + <item path="../miosix/filesystem/ioctl.h" ex="false" tool="3" flavor2="0"> + </item> <item path="../miosix/filesystem/mountpointfs/mountpointfs.cpp" ex="false" tool="1" diff --git a/miosix_np_2/nbproject/private/configurations.xml b/miosix_np_2/nbproject/private/configurations.xml index 5f2c4c7e04c9a2ada54af541f3639f8841e8b7f5..4feb0c506f368c2949df619fdc2a98176254cc48 100644 --- a/miosix_np_2/nbproject/private/configurations.xml +++ b/miosix_np_2/nbproject/private/configurations.xml @@ -313,8 +313,6 @@ <in>console_device.h</in> </df> <df name="devfs"> - <in>base_files.cpp</in> - <in>base_files.h</in> <in>devfs.cpp</in> <in>devfs.h</in> </df> @@ -338,6 +336,7 @@ <in>file.h</in> <in>file_access.cpp</in> <in>file_access.h</in> + <in>ioctl.h</in> <in>stringpart.cpp</in> <in>stringpart.h</in> </df>