summaryrefslogtreecommitdiff
path: root/firmware/export/fat.h
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/export/fat.h')
-rw-r--r--firmware/export/fat.h225
1 files changed, 135 insertions, 90 deletions
diff --git a/firmware/export/fat.h b/firmware/export/fat.h
index a0d52acc35..3aa1e254dc 100644
--- a/firmware/export/fat.h
+++ b/firmware/export/fat.h
@@ -18,123 +18,168 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21
22#ifndef FAT_H 21#ifndef FAT_H
23#define FAT_H 22#define FAT_H
24 23
25#include <stdbool.h> 24#include <stdbool.h>
26#include "mv.h" /* for volume definitions */ 25#include <sys/types.h>
26#include <time.h>
27#include "config.h" 27#include "config.h"
28#include "system.h" 28#include "system.h"
29#include "mv.h" /* for volume definitions */
30
31/********
32 **** DO NOT use these functions directly unless otherwise noted. Required
33 **** synchronization is done by higher-level interfaces to minimize locking
34 **** overhead.
35 ****
36 **** Volume, drive, string, etc. parameters should also be checked by
37 **** callers for gross violations-- NULL strings, out-of-bounds values,
38 **** etc.
39 ****/
40
41/****************************************************************************
42 ** Values that can be overridden by a target in config-[target].h
43 **/
44
45/* if your ATA implementation can do better, go right ahead and increase this
46 * value */
47#ifndef FAT_MAX_TRANSFER_SIZE
48#define FAT_MAX_TRANSFER_SIZE 256
49#endif
29 50
30/* This value can be overwritten by a target in config-[target].h, but 51/* still experimental? */
31 that behaviour is still experimental */ 52/* increasing this will increase the total memory used by the cache; the
53 cache, as noted in disk_cache.h, has other minimum requirements that may
54 prevent reducing its number of entries in order to compensate */
32#ifndef SECTOR_SIZE 55#ifndef SECTOR_SIZE
33#define SECTOR_SIZE 512 56#define SECTOR_SIZE 512
34#endif 57#endif
35 58
59/**
60 ****************************************************************************/
61
62#define INVALID_SECNUM (0xfffffffeul) /* sequential, not FAT */
63#define FAT_MAX_FILE_SIZE (0xfffffffful) /* 2^32-1 bytes */
64#define MAX_DIRENTRIES 65536
65#define MAX_DIRECTORY_SIZE (MAX_DIRENTRIES*32) /* 2MB max size */
66
67/* these aren't I/O error conditions, so define specially; failure rc's
68 * shouldn't return the last digit as "0", therefore this is unambiguous */
69#define FAT_RC_ENOSPC (-10)
70#define FAT_SEEK_EOF (-20)
71
36/* Number of bytes reserved for a file name (including the trailing \0). 72/* Number of bytes reserved for a file name (including the trailing \0).
37 Since names are stored in the entry as UTF-8, we won't be able to 73 Since names are stored in the entry as UTF-8, we won't be ble to
38 store all names allowed by FAT. In FAT, a name can have max 255 74 store all names allowed by FAT. In FAT, a name can have max 255
39 characters (not bytes!). Since the UTF-8 encoding of a char may take 75 characters (not bytes!). Since the UTF-8 encoding of a char may take
40 up to 4 bytes, there will be names that we won't be able to store 76 up to 4 bytes, there will be names that we won't be able to store
41 completely. For such names, the short DOS name is used. */ 77 completely. For such names, the short DOS name is used. */
42#define FAT_FILENAME_BYTES 256 78#define FAT_DIRENTRY_NAME_MAX 255
43
44struct fat_direntry 79struct fat_direntry
45{ 80{
46 unsigned char name[FAT_FILENAME_BYTES]; /* UTF-8 encoded name plus \0 */ 81 union {
47 unsigned short attr; /* Attributes */ 82 uint8_t name[255+1+4]; /* UTF-8 name plus \0 plus parse slop */
48 unsigned char crttimetenth; /* Millisecond creation 83 uint16_t ucssegs[5+20][13]; /* UTF-16 segment buffer - layout saves... */
49 time stamp (0-199) */ 84 }; /* ...130 bytes (important if stacked) */
50 unsigned short crttime; /* Creation time */ 85 uint16_t ucsterm; /* allow one NULL-term after ucssegs */
51 unsigned short crtdate; /* Creation date */ 86 uint8_t shortname[13]; /* DOS filename (OEM charset) */
52 unsigned short lstaccdate; /* Last access date */ 87 uint8_t attr; /* file attributes */
53 unsigned short wrttime; /* Last write time */ 88 uint8_t crttimetenth; /* millisecond creation time stamp (0-199) */
54 unsigned short wrtdate; /* Last write date */ 89 uint16_t crttime; /* creation time */
55 unsigned long filesize; /* File size in bytes */ 90 uint16_t crtdate; /* creation date */
56 long firstcluster; /* fstclusterhi<<16 + fstcluslo */ 91 uint16_t lstaccdate; /* last access date */
92 uint16_t wrttime; /* last write time */
93 uint16_t wrtdate; /* last write date */
94 uint32_t filesize; /* file size in bytes */
95 int32_t firstcluster; /* first FAT cluster of file, 0 if empty */
57}; 96};
58 97
59#define FAT_ATTR_READ_ONLY 0x01 98/* cursor structure used for scanning directories; holds the last-returned
60#define FAT_ATTR_HIDDEN 0x02 99 entry information */
61#define FAT_ATTR_SYSTEM 0x04 100struct fat_dirscan_info
62#define FAT_ATTR_VOLUME_ID 0x08 101{
63#define FAT_ATTR_DIRECTORY 0x10 102 unsigned int entry; /* short dir entry index in parent */
64#define FAT_ATTR_ARCHIVE 0x20 103 unsigned int entries; /* number of dir entries used */
65#define FAT_ATTR_VOLUME 0x40 /* this is a volume, not a real directory */ 104};
105
106#define FAT_RW_VAL (0u - 1)
66 107
108/* basic FAT file information about where to find a file and who houses it */
67struct fat_file 109struct fat_file
68{ 110{
69 long firstcluster; /* first cluster in file */
70 long lastcluster; /* cluster of last access */
71 long lastsector; /* sector of last access */
72 long clusternum; /* current clusternum */
73 long sectornum; /* sector number in this cluster */
74 unsigned int direntry; /* short dir entry index from start of dir */
75 unsigned int direntries; /* number of dir entries used by this file */
76 long dircluster; /* first cluster of dir */
77 bool eof;
78#ifdef HAVE_MULTIVOLUME 111#ifdef HAVE_MULTIVOLUME
79 int volume; /* file resides on which volume */ 112 int volume; /* file resides on which volume (first!) */
80#endif 113#endif
114 long firstcluster; /* first cluster in file */
115 long dircluster; /* first cluster of parent directory */
116 struct fat_dirscan_info e; /* entry information */
81}; 117};
82 118
83struct fat_dir 119/* this stores what was last accessed when read or writing a file's data */
120struct fat_filestr
84{ 121{
85 unsigned char sectorcache[SECTOR_SIZE] CACHEALIGN_ATTR; 122 struct fat_file *fatfilep; /* common file information */
86 unsigned int entry; 123 long lastcluster; /* cluster of last access */
87 unsigned int entrycount; 124 unsigned long lastsector; /* sector of last access */
88 long sector; 125 long clusternum; /* cluster number of last access */
89 struct fat_file file; 126 unsigned long sectornum; /* sector number within current cluster */
90 /* There are 2-bytes per characters. We don't want to bother too much, as LFN entries are 127 bool eof; /* end-of-file reached */
91 * at much 255 characters longs, that's at most 20 LFN entries. Each entry hold at most 128};
92 * 13 characters, that a total of 260 characters. So we keep a buffer of that size. 129
93 * Keep coherent with fat.c code. */ 130/** File entity functions **/
94 unsigned char longname[260 * 2]; 131int fat_create_file(struct fat_file *parent, const char *name,
95} CACHEALIGN_ATTR; 132 uint8_t attr, struct fat_file *file,
96 133 struct fat_direntry *fatent);
97#ifdef HAVE_HOTSWAP 134bool fat_dir_is_parent(const struct fat_file *dir, const struct fat_file *file);
98extern void fat_lock(void); 135bool fat_file_is_same(const struct fat_file *file1, const struct fat_file *file2);
99extern void fat_unlock(void); 136int fat_fstat(struct fat_file *file, struct fat_direntry *entry);
100#endif 137int fat_open(const struct fat_file *parent, long startcluster,
138 struct fat_file *file);
139int fat_open_rootdir(IF_MV(int volume,) struct fat_file *dir);
140enum fat_remove_op /* what should fat_remove(), remove? */
141{
142 FAT_RM_DIRENTRIES = 0x1, /* remove only directory entries */
143 FAT_RM_DATA = 0x2, /* remove only file data */
144 FAT_RM_ALL = 0x3, /* remove all of above */
145};
146int fat_remove(struct fat_file *file, enum fat_remove_op what);
147int fat_rename(struct fat_file *parent, struct fat_file *file,
148 const unsigned char *newname);
101 149
102extern void fat_init(void); 150/** File stream functions **/
103extern int fat_get_bytes_per_sector(IF_MV_NONVOID(int volume)); 151int fat_closewrite(struct fat_filestr *filestr, uint32_t size,
104extern int fat_mount(IF_MV(int volume,) IF_MD(int drive,) long startsector); 152 struct fat_direntry *fatentp);
105extern int fat_unmount(int volume, bool flush); 153void fat_filestr_init(struct fat_filestr *filestr, struct fat_file *file);
106extern void fat_size(IF_MV(int volume,) /* public for info */ 154unsigned long fat_query_sectornum(const struct fat_filestr *filestr);
107 unsigned long* size, 155long fat_readwrite(struct fat_filestr *filestr, unsigned long sectorcount,
108 unsigned long* free); 156 void *buf, bool write);
109extern void fat_recalc_free(IF_MV_NONVOID(int volume)); /* public for debug info screen */ 157void fat_rewind(struct fat_filestr *filestr);
110extern int fat_create_dir(const char* name, 158int fat_seek(struct fat_filestr *filestr, unsigned long sector);
111 struct fat_dir* newdir, 159int fat_truncate(const struct fat_filestr *filestr);
112 struct fat_dir* dir);
113extern int fat_open(IF_MV(int volume,)
114 long cluster,
115 struct fat_file* ent,
116 const struct fat_dir* dir);
117extern int fat_create_file(const char* name,
118 struct fat_file* ent,
119 struct fat_dir* dir);
120extern long fat_readwrite(struct fat_file *ent, long sectorcount,
121 void* buf, bool write );
122extern int fat_closewrite(struct fat_file *ent, long size, int attr);
123extern int fat_seek(struct fat_file *ent, unsigned long sector );
124extern int fat_remove(struct fat_file *ent);
125extern int fat_truncate(const struct fat_file *ent);
126extern int fat_rename(struct fat_file* file,
127 struct fat_dir* dir,
128 const unsigned char* newname,
129 long size, int attr);
130
131extern int fat_opendir(IF_MV(int volume,)
132 struct fat_dir *ent, unsigned long startcluster,
133 const struct fat_dir *parent_dir);
134extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry);
135extern unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume)); /* public for debug info screen */
136extern bool fat_ismounted(int volume);
137extern void* fat_get_sector_buffer(void);
138extern void fat_release_sector_buffer(void);
139 160
140#endif 161/** Directory stream functions **/
162struct filestr_cache;
163int fat_readdir(struct fat_filestr *dirstr, struct fat_dirscan_info *scan,
164 struct filestr_cache *cachep, struct fat_direntry *entry);
165void fat_rewinddir(struct fat_dirscan_info *scan);
166
167/** Mounting and unmounting functions **/
168bool fat_ismounted(IF_MV_NONVOID(int volume));
169int fat_mount(IF_MV(int volume,) IF_MD(int drive,) unsigned long startsector);
170int fat_unmount(IF_MV_NONVOID(int volume));
171
172/** Debug screen stuff **/
173#ifdef MAX_LOG_SECTOR_SIZE
174int fat_get_bytes_per_sector(IF_MV_NONVOID(int volume));
175#endif /* MAX_LOG_SECTOR_SIZE */
176unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume));
177void fat_recalc_free(IF_MV_NONVOID(int volume));
178bool fat_size(IF_MV(int volume,) unsigned long *size, unsigned long *free);
179
180/** Misc. **/
181time_t fattime_mktime(uint16_t fatdate, uint16_t fattime);
182void fat_empty_fat_direntry(struct fat_direntry *entry);
183void fat_init(void);
184
185#endif /* FAT_H */