⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat16.c

📁 SD卡调试所用的资料
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Includes ------------------------------------------------------------------*/
#include "fat16.h"
#include <string.h>

#if USE_DYNAMIC_MEMORY
    #include <stdlib.h>
#endif


#define FAT16_CLUSTER_FREE 0x0000
#define FAT16_CLUSTER_RESERVED_MIN 0xfff0
#define FAT16_CLUSTER_RESERVED_MAX 0xfff6
#define FAT16_CLUSTER_BAD 0xfff7
#define FAT16_CLUSTER_LAST_MIN 0xfff8
#define FAT16_CLUSTER_LAST_MAX 0xffff

#define FAT16_DIRENTRY_DELETED 0xe5
#define FAT16_DIRENTRY_LFNLAST (1 << 6)
#define FAT16_DIRENTRY_LFNSEQMASK ((1 << 6) - 1)


/* Each entry within the directory table has a size of 32 bytes
 * and either contains a 8.3 DOS-style file name or a part of a
 * long file name, which may consist of several directory table
 * entries at once.
 *
 * multi-byte integer values are stored little-endian!
 *
 * 8.3 file name entry:
 * ====================
 * offset  length  description
 *      0       8  name (space padded)
 *      8       3  extension (space padded)
 *     11       1  Attributes (FAT16_ATTRIB_*)
 *
 * long file name (lfn) entry ordering for a single file name:
 * ===========================================================
 * LFN entry n
 *     ...
 * LFN entry 2
 * LFN entry 1
 * 8.3 entry (see above)
 *
 * lfn entry:
 * ==========
 * offset  length  description
 *      0       1  ordinal field
 *      1       2  unicode character 1
 *      3       3  unicode character 2
 *      5       3  unicode character 3
 *      7       3  unicode character 4
 *      9       3  unicode character 5
 *     11       1  attribute (always 0x0f)
 *     12       1  type (reserved, always 0)
 *     13       1  checksum
 *     14       2  unicode character 6
 *     16       2  unicode character 7
 *     18       2  unicode character 8
 *     20       2  unicode character 9
 *     22       2  unicode character 10
 *     24       2  unicode character 11
 *     26       2  Cluster (unused, always 0)
 *     28       2  unicode character 12
 *     30       2  unicode character 13
 *
 * The ordinal field contains a descending number, from n to 1.
 * For the n'th lfn entry the ordinal field is or'ed with 0x40.
 * For deleted lfn entries, the ordinal field is set to 0xe5.
 */

struct Fat16_Header_Struct
{
    u32 Size;
    u32 Fat_Offset;
    u32 Fat_Size;
    u16 Sector_Size;
    u16 Cluster_Size;
    u32 Root_Dir_Offset;
    u32 Cluster_Zero_Offset;
};

struct Fat16_FS_Struct
{
    struct Partition_Struct*    partition;
    struct Fat16_Header_Struct  header;
};

struct Fat16_File_Struct
{
    struct Fat16_FS_Struct*         fs;
    struct Fat16_Dir_Entry_Struct   dir_entry;
    u32                             pos;
    u16                             pos_cluster;
};

struct Fat16_Dir_Struct
{
    struct Fat16_FS_Struct*         fs;
    struct Fat16_Dir_Entry_Struct   dir_entry;
    u16                             entry_next;
};

struct Fat16_Read_CallBack_Arg
{
    u16   Entry_Cur;
    u16   Entry_Num;
    u32   Entry_Offset;
    u8    Byte_Count;
};

struct Fat16_Usage_Count_CallBack_Arg
{
    u16   cluster_count;
    u8    buffer_size;
};

#if !USE_DYNAMIC_MEMORY
static struct Fat16_FS_Struct     fat16_fs_handlers[FAT16_FS_COUNT];
static struct Fat16_File_Struct   fat16_file_handlers[FAT16_FILE_COUNT];
static struct Fat16_Dir_Struct    fat16_dir_handlers[FAT16_DIR_COUNT];
#endif

static u8   Fat16_Read_Header(struct Fat16_FS_Struct* fs);

static u8   Fat16_Read_Root_Dir_Entry(const struct Fat16_FS_Struct*         fs,
                                      u16                                   Entry_Num, 
                                      struct Fat16_Dir_Entry_Struct*        dir_entry);

static u8   Fat16_Read_Sub_Dir_Entry(const struct Fat16_FS_Struct*          fs,
                                     u16                                    Entry_Num,
                                     const struct Fat16_Dir_Entry_Struct*   parent,
                                     struct Fat16_Dir_Entry_Struct*         dir_entry);

static u8   Fat16_Dir_Entry_Seek_CallBack(u8* buffer, u32 offset, void* p);

static u8   Fat16_Dir_Entry_Read_CallBack(u8* buffer, u32 offset, void* p);

static u8   Fat16_Interpret_Dir_Entry(struct Fat16_Dir_Entry_Struct* dir_entry, const u8* raw_entry);

static u16  Fat16_Get_Next_Cluster(const struct Fat16_FS_Struct* fs, u16 cluster_num);

static u16  Fat16_Append_Clusters(const struct Fat16_FS_Struct* fs, u16 cluster_num, u16 count);

static u8   Fat16_Free_Clusters(const struct Fat16_FS_Struct* fs, u16 cluster_num);

static u8   Fat16_Terminate_Clusters(const struct Fat16_FS_Struct* fs, u16 cluster_num);

static u8   Fat16_Clear_Cluster(const struct Fat16_FS_Struct* fs, u16 cluster_num);

static u16  Fat16_Clear_Cluster_CallBack(u8* buffer, u32 offset, void* p);

static u32  Fat16_Find_Offset_For_Dir_Entry(const struct Fat16_FS_Struct*         fs,
                                            const struct Fat16_Dir_Struct*        parent,
                                            const struct Fat16_Dir_Entry_Struct*  dir_entry);

static u8   Fat16_Write_Dir_Entry(const struct Fat16_FS_Struct*   fs,
                                  struct Fat16_Dir_Entry_Struct*  dir_entry);

static u8 Fat16_Get_FS_Free_CallBack(u8* buffer, u32 offset, void* p);

//static void fat16_set_file_modification_date(struct Fat16_Dir_Entry_Struct* dir_entry, u16 year, u8 month, u8 day);
//static void fat16_set_file_modification_time(struct Fat16_Dir_Entry_Struct* dir_entry, u8 hour, u8 min, u8 sec);


/**********************************************************************
*  函数 Fat16_Open --- 打开FAT16文件系统
*  输入参数 partition:文件系统所在的分区
*  返回值  0 ---打开错误 
*          其他 ---文件系统信息
**********************************************************************/
struct Fat16_FS_Struct* 
Fat16_Open(struct Partition_Struct* partition)
{
    if(!partition ||
#if FAT16_WRITE_SUPPORT
       !partition->device_write ||
       !partition->device_write_interval
#else
       False
#endif
      )
        return False;

#if USE_DYNAMIC_MEMORY
    struct Fat16_FS_Struct* fs = malloc(sizeof(*fs));
    if(!fs) return False;
#else
    struct Fat16_FS_Struct* fs = fat16_fs_handlers;
    u8 i;
    for(i = 0; i < FAT16_FS_COUNT; ++i)
    {
        if(!fs->partition)
            break;

        ++fs;
    }
    if(i >= FAT16_FS_COUNT) return False;
#endif

    memset(fs, 0, sizeof(*fs));
    fs->partition = partition;
    
    if(!Fat16_Read_Header(fs))
    {
#if USE_DYNAMIC_MEMORY
        free(fs);
#else
        fs->partition = 0;
#endif
        return False;
    }

    return fs;
}



/**********************************************************************
*  函数 Fat16_Close --- 关闭FAT16文件系统
*  输入参数 fs:所需关闭的文件系统
*  返回值  无
**********************************************************************/
void 
Fat16_Close(struct Fat16_FS_Struct* fs)
{
    if(!fs)
        return;

#if USE_DYNAMIC_MEMORY
    free(fs);
#else
    fs->partition = 0;
#endif
}



/**********************************************************************
*  函数 Fat16_Read_Header --- 读取并解释 the header of a FAT16 filesystem 
*  输出参数 fs:The filesystem for which to parse the header.
*  返回值  0 --- 失败
*          1 --- 成功
**********************************************************************/
u8 
Fat16_Read_Header(struct Fat16_FS_Struct* fs)
{
    if(!fs)
        return False;

    struct Partition_Struct* partition = fs->partition;
    if(!partition)
        return False;

    /* read fat parameters */
    u8 buffer[25];
    u32 partition_offset = partition->offset * 512;
    if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
        return False;

    u16 bytes_per_sector = ((u16) buffer[0x00]) |
                                ((u16) buffer[0x01] << 8);
    u8 sectors_per_cluster = buffer[0x02];
    u16 reserved_sectors = ((u16) buffer[0x03]) |
                                ((u16) buffer[0x04] << 8);
    u8 fat_copies = buffer[0x05];
    u16 max_root_entries = ((u16) buffer[0x06]) |
                                ((u16) buffer[0x07] << 8);
    u16 sector_count_16 = ((u16) buffer[0x08]) |
                               ((u16) buffer[0x09] << 8);
    u16 sectors_per_fat = ((u16) buffer[0x0b]) |
                               ((u16) buffer[0x0c] << 8);
    u32 sector_count = ((u32) buffer[0x15]) |
                            ((u32) buffer[0x16] << 8) |
                            ((u32) buffer[0x17] << 16) |
                            ((u32) buffer[0x18] << 24);

    if(sectors_per_fat == 0)
        /* this is not a FAT16 */
        return False;

    if(sector_count == 0)
    {
        if(sector_count_16 == 0)
            /* illegal volume size */
            return False;
        else
            sector_count = sector_count_16;
    }

    /* ensure we really have a FAT16 fs here */
    u32 data_sector_count = sector_count
                                 - reserved_sectors
                                 - (u32) sectors_per_fat * fat_copies
                                 - ((max_root_entries * 32 + bytes_per_sector - 1) / bytes_per_sector);
    u32 data_cluster_count = data_sector_count / sectors_per_cluster;
    if(data_cluster_count < 4085 || data_cluster_count >= 65525)
        /* this is not a FAT16 */
        return False;

    partition->type = PARTITION_TYPE_FAT16;

    /* fill header information */
    struct Fat16_Header_Struct* header = &fs->header;
    memset(header, 0, sizeof(*header));

    header->Size = sector_count * bytes_per_sector;

    header->Fat_Offset = /* jump to partition */
                         partition_offset +
                         /* jump to fat */
                         (u32) reserved_sectors * bytes_per_sector;
    header->Fat_Size = (data_cluster_count + 2) * 2;

    header->Sector_Size = bytes_per_sector;
    header->Cluster_Size = (u32) bytes_per_sector * sectors_per_cluster;

    header->Root_Dir_Offset = /* jump to fats */
                              header->Fat_Offset +
                              /* jump to root directory entries */
                              (u32) fat_copies * sectors_per_fat * bytes_per_sector;

    header->Cluster_Zero_Offset = /* jump to root directory entries */
                                  header->Root_Dir_Offset +
                                  /* skip root directory entries */
                                  (u32) max_root_entries * 32;

    return True;
}


/**********************************************************************
*  函数 Fat16_Read_Root_Dir_Entry
*         --- 读取目录项的根目录
*  输入参数 fs:文件系统
*           Entry_Num:目录项标号
*  输出参数 dir_entry:输出目录结构参数   
*  返回值  0 --- 失败
*          1 --- 成功
**********************************************************************/
u8 
Fat16_Read_Root_Dir_Entry(const struct Fat16_FS_Struct*     fs,
                          u16                               Entry_Num, 
                          struct Fat16_Dir_Entry_Struct*    dir_entry)
{
    if(!fs || !dir_entry)
        return 0;

    /* we read from the root directory entry */
    const struct Fat16_Header_Struct* header = &fs->header;
    device_read_interval_t device_read_interval = fs->partition->device_read_interval;
    u8 buffer[32];

    /* seek to the n-th entry */
    struct Fat16_Read_CallBack_Arg arg;
    memset(&arg, 0, sizeof(arg));
    arg.Entry_Num = Entry_Num;
    if(!device_read_interval(header->Root_Dir_Offset,
                             buffer,
                             sizeof(buffer),
                             header->Cluster_Zero_Offset - header->Root_Dir_Offset,
                             Fat16_Dir_Entry_Seek_CallBack,
                             &arg) ||
       arg.Entry_Offset == 0
      )
        return 0;

    /* read entry */
    memset(dir_entry, 0, sizeof(*dir_entry));
    if(!device_read_interval(arg.Entry_Offset,
                             buffer,
                             sizeof(buffer),
                             arg.Byte_Count,
                             Fat16_Dir_Entry_Read_CallBack,
                             dir_entry))
        return 0;

    return dir_entry->Long_Name[0] != '\0' ? 1 : 0;
}


/**********************************************************************
*  函数 Fat16_Read_Sub_Dir_Entry
*         --- 读取下级目录
*  输入参数 fs:文件系统
*           Entry_Num:子目录项标号
*           parent:父目录
*  输出参数 dir_entry:输出目录结构参数   
*  返回值  0 --- 失败
*          1 --- 成功
**********************************************************************/
u8 
Fat16_Read_Sub_Dir_Entry(const struct Fat16_FS_Struct*          fs,
                         u16                                    Entry_Num, 
                         const struct Fat16_Dir_Entry_Struct*   parent,
                         struct Fat16_Dir_Entry_Struct*         dir_entry)
{
    if(!fs || !parent || !dir_entry)
        return 0;

    /* we are in a parent directory and want to search within its directory entry table */
    if(!(parent->Attributes & FAT16_ATTRIB_DIR))
        return 0;
	
    /* loop through all clusters of the directory */
    u8 buffer[32];
    u32 cluster_offset;
    u16 Cluster_Size = fs->header.Cluster_Size;
    u16 cluster_num = parent->Cluster;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -