Class that contain only FATFileSystem

Fork of USBFileSystem by Erik -

USBFileSystem.h

Committer:
Sissors
Date:
2013-10-23
Revision:
2:9af05743d551
Parent:
1:4ba08d11e36e
Child:
6:eeeea7fbb0a2

File content as of revision 2:9af05743d551:

#ifndef USBFILESYSTEM_H
#define USBFILESYSTEM_H

#include "FATFileSystem.h"
#include "USBMSD.h"
#include "FATFileHandle.h"

class FATFileSystem_ds : public FATFileSystem {    
    public:
    FATFileSystem_ds(const char* n) : FATFileSystem(n) {};
    
    protected:
    virtual int disk_status_fat( void ) = 0;
    virtual int disk_status( void ) {return disk_status_fat();}
};

class USBMSD_ds : public USBMSD {    
    public:
    USBMSD_ds() {};
    
    protected:
    virtual int disk_status_msd( void ) = 0;
    virtual int disk_status( void ) {return disk_status_msd();}
};

/** Class which combines FATFileSystem with USBMSD device
*
* The functions to be implemented by the child class are the same as
* those that have to be implemented when using FATFileSystem/USBMSD.
* However there are some caveats: _disk_status() and _disk_write MUST
* be named with the '_' in front of it. You are not allowed to have a
* function without the '_'. Those functions may not be inherited, but
* with this version of C++ I cannot prevent the child from doing so.
*
* Next the size of a disk sector must be 512 bytes. This is because
* FATFileSystem only accepts that. If disk_size is not implemented
* this is done automatically. 
*
* What the library does is block write access locally when USB writes,
* and USB write access is blocked when with fopen a file is opened for
* write locally. This way they can't both write at the same time. Read
* access is not blocked.
*
* The final issue to take into account is caching: FATFileSystem will not
* re-open a file if you read twice the same data from it. So if USBMSD
* changed it, it will not show up different. If you close the file and
* call fopen again it will work. The USBMSD part has the
* same issue, but worse. Windows at least will only load everything once!
* So if you open a file, and then change it manually, you will never find
* out until the device is disconnected. If the disk is write protected
* it will not tell you so. It will write/delete what you want, only when
* you reconnect the device will it show it didn't actually do anything!
*
* See the program's wiki for more documentation!
*/
class USBFileSystem : public FATFileSystem_ds, public USBMSD_ds {
public:
    /** 
    * Constructor for USBFileSystem
    *
    * @param n - Name for the file system
    */
    USBFileSystem(const char* n);
    
    /** Attach a function to be called when locally the filesystem is occupied/freed
    *
    * The function is called with 'true' as argument when it is freed, false when it is occupied
    *
    * @param function - Function to be called, must have void as return type, and a single boolean argument
    */
    void attachLocal(void (*function)(bool));
    
    /** Attach a function to be called when USB occupies/frees the filesystem 
    *
    * The function is called with 'true' as argument when it is freed, false when it is occupied
    *
    * @param function - Function to be called, must have void as return type, and a single boolean argument
    */
    void attachUSB(void (*function)(bool));
    
    /** Check if locally files are opened for write
    *
    * @return - true if none are opened for write, false otherwise
    */
    bool localSafe( void );
    
    /** Check if via USB files files are being written
    *
    * @return - true if none are being written, false otherwise
    */
    bool usbSafe( void );
    
    /** Sets the USB mode
    *
    * Argument = 0: USB is write protected when not available.
    * Argument = 1: USB is disconnected when not available (default).
    *
    * @param mode - USB safety mode
    */
    void usbMode( int mode );
    
    
protected:
    //Functions to be implemented by child:
    virtual int disk_initialize() { return 0; }
    virtual int _disk_status() { return 0; }
    virtual int disk_read(uint8_t * buffer, uint64_t sector) { return 0;}
    virtual int _disk_write(const uint8_t * buffer, uint64_t sector) = 0;
    virtual int disk_sync() { return 0; }
    virtual uint64_t disk_sectors() = 0;
    virtual uint64_t disk_size() {return 512 * disk_sectors();}
    
    //Not to be implemented by child:
    virtual FileHandle* open(const char* name, int flags);
    void localOpen( bool open );
    void usbFree( void );
    
private:
    virtual int disk_status_fat(void);
    virtual int disk_status_msd(void);
    virtual int disk_write(const uint8_t * buffer, uint64_t sector);
    
    int local_count;
    int usbmode;
    Timeout usb_write;
    bool usbfree;
    
    void (*localFunction)(bool);
    void (*usbFunction)(bool);
    
    friend class USBFileHandle;

};


class USBFileHandle : public FATFileHandle {    
    public:
    USBFileHandle(FIL fh, USBFileSystem *p, bool write) : FATFileHandle(fh) {
     _p = p;
     _write = write;
    }
    
    protected:
    USBFileSystem *_p;
    bool _write;
    
    virtual int close() {
        int retval = FATFileHandle::close();
        if (_write)
            _p->localOpen(false);
        return retval;
        }
};





#endif