Subversion Repositories NaviCtrl

Rev

Rev 24 | Rev 70 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 24 Rev 41
1
/*#######################################################################################*/
1
/*#######################################################################################*/
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
3
/*#######################################################################################*/
3
/*#######################################################################################*/
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5
// + Copyright (c) 2008 Ingo Busker, Holger Buss
5
// + Copyright (c) 2008 Ingo Busker, Holger Buss
6
// + Nur für den privaten Gebrauch
6
// + Nur für den privaten Gebrauch
7
// + FOR NON COMMERCIAL USE ONLY
7
// + FOR NON COMMERCIAL USE ONLY
8
// + www.MikroKopter.com
8
// + www.MikroKopter.com
9
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation), 
10
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation), 
11
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist. 
11
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist. 
12
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt 
12
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt 
13
// + bzgl. der Nutzungsbedingungen aufzunehmen. 
13
// + bzgl. der Nutzungsbedingungen aufzunehmen. 
14
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
14
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
15
// + Verkauf von Luftbildaufnahmen, usw.
15
// + Verkauf von Luftbildaufnahmen, usw.
16
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht, 
17
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht, 
18
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
18
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
20
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
21
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
21
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
22
// + eindeutig als Ursprung verlinkt werden
22
// + eindeutig als Ursprung verlinkt werden
23
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
24
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
25
// + Benutzung auf eigene Gefahr
25
// + Benutzung auf eigene Gefahr
26
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
26
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
27
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
28
// + Die PORTIERUNG der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur 
28
// + Die PORTIERUNG der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur 
29
// + mit unserer Zustimmung zulässig
29
// + mit unserer Zustimmung zulässig
30
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
31
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
32
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
32
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33
// + Redistributions of source code (with or without modifications) must retain the above copyright notice, 
33
// + Redistributions of source code (with or without modifications) must retain the above copyright notice, 
34
// + this list of conditions and the following disclaimer.
34
// + this list of conditions and the following disclaimer.
35
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
35
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
36
// +     from this software without specific prior written permission.
36
// +     from this software without specific prior written permission.
37
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permitted 
37
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permitted 
38
// +     for non-commercial use (directly or indirectly)
38
// +     for non-commercial use (directly or indirectly)
39
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted 
39
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted 
40
// +     with our written permission
40
// +     with our written permission
41
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be 
41
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be 
42
// +     clearly linked as origin 
42
// +     clearly linked as origin 
43
// +   * PORTING this software (or part of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
43
// +   * PORTING this software (or part of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
44
//
44
//
45
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
45
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
46
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
48
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
49
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53
// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53
// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
54
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55
// +  POSSIBILITY OF SUCH DAMAGE. 
55
// +  POSSIBILITY OF SUCH DAMAGE. 
56
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
 
57
#include <stdio.h>
-
 
58
#include "91x_lib.h"
-
 
59
#include "timer.h"
-
 
60
#include "fat16.h"
-
 
61
#include "sdc.h"
-
 
62
#include "uart1.h"
57
 
-
 
58
#include "main.h"
63
 
59
 
64
 
60
//________________________________________________________________________________________________________________________________________
65
//________________________________________________________________________________________________________________________________________
61
// Module name:                 fat16.c 
66
// Module name:                 fat16.c 
62
// Compiler used:               avr-gcc 3.4.5
67
// Compiler used:               avr-gcc 3.4.5
63
// Last Modifikation:   21.04.2008
68
// Last Modifikation:   16.06.2008
64
// Version:                             1.28
69
// Version:                             2.00
65
// Authors:                             Stephan Busker  
70
// Authors:                             Stephan Busker & Gregor Stobrawa        
66
// Description:                 Source files for FAT16 implementation with read and write-access using AVR-Mikrocontrollers
71
// Description:                 Source files for FAT16 implementation with read and write-access
67
//                                              Copyright (C) 2007 Stephan Busker
72
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
68
//........................................................................................................................................
73
//........................................................................................................................................
69
// Functions:                   extern u8       InitFat16(void);                
74
// Functions:                   extern s16              Fat16_Init(void);
70
//                                              u8                      fopen_(s8 *fname,s8 mode, File *file);
75
//                                              extern s16              Fat16_Deinit(void);             
71
//                                              void            fclose_(File *file);
76
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
72
//                                              u32             fread_(void *buffer, u32 size, u32 count, File *file); 
77
//                                              extern s16              fclose_(File_t *File);
73
//                                              u32             fwrite_(void *buffer, u32 size, u32 count, File *file);
78
//                                              extern s16              fflush_(File_t *File);
74
//                                              s16             fseek_(File *file, s32 offset, s16 origin);
79
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
75
//                                      s8                      fgets_(s8 *string, s16 count, File *file);
-
 
76
//                                              u8                      fputchar_(File *file,s8 c);
80
//                                              extern s16              fgetc_(File_t *File);
77
//                                              u8                      fputs_(File *file,s8 *string);
81
//                                              extern s16              fputc_(u8 c, File_t *File);
78
//                                              s8 *            fgets(s8 *, s16, File);
82
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File); 
79
//                                              u8                      fexist_(u8*);
-
 
80
//                                              u8                      mkdir__(s8 *name);
-
 
81
//                                              u8                      chdir__(s8 *name);
-
 
82
//                                              u8                      findfirst_(s8 *fname, Find *item, u8 attribute);
83
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
83
//                                              u8                      findnext_(Find *item);
84
//                                              extern s16              fputs_(const u8 *string, File_t *File);
84
//                                              u8                      fdelete_(s8 *fname)
85
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
85
//                                              u8                      rmdir_(s8 *dname)
-
 
86
//                                              u16                     feof_(File);
-
 
87
//........................................................................................................................................
86
//........................................................................................................................................
88
// ext. functions:              extern u8 SDC_GetSector  (u32,u8 *);            
87
// ext. functions:              extern SD_Result_t SDC_Init(void;)
-
 
88
//                                              extern SD_Result_t SDC_Deinit(void);
-
 
89
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);            
89
//                                              extern u8 SDC_PutSector (u32,u8 *);
90
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
90
//........................................................................................................................................
91
//........................................................................................................................................
91
//
92
//
92
// URL:                                 www.Mikro-Control.de
93
// URL:                                 www.Mikro-Control.de
93
// mailto:                              stephan.busker@mikro-control.de
94
// mailto:                              stephan.busker@mikro-control.de
94
//________________________________________________________________________________________________________________________________________
95
//________________________________________________________________________________________________________________________________________
-
 
96
 
-
 
97
/*
-
 
98
FAT16 Drive Layout:
-
 
99
Description                                             Offset
-
 
100
Volume Boot Sector                                      Start of Partition
-
 
101
Fat Tables                                                      Start + # of Reserved Sectors
-
 
102
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
-
 
103
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
95
 
104
*/
-
 
105
 
-
 
106
 
-
 
107
/*
96
 
108
________________________________________________________________________________________________________________________________________
-
 
109
 
97
 
110
        Structure of an partition entry                        
-
 
111
________________________________________________________________________________________________________________________________________
-
 
112
 
-
 
113
        Partition Entry is 16 bytes long
-
 
114
*/
-
 
115
typedef struct
-
 
116
{
-
 
117
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
-
 
118
        u8      BeginningHead;                          // Beginning of Partition - Head
-
 
119
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
-
 
120
        u8      Type;                                           // Type of Partition (See List Below)
-
 
121
        u8      EndHead;                                        // End of Partition - Head
-
 
122
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
-
 
123
        u32     NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
-
 
124
        u32     NoSectorsPartition      ;               // Number of Sectors in the Partition
-
 
125
} __attribute__((packed)) PartitionEntry_t;
-
 
126
 
-
 
127
/*
-
 
128
Coding of Cylinder/Sector words
-
 
129
 
-
 
130
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
-
 
131
Sector is 5 bits:  [5:0] at [5:0]  
-
 
132
*/
-
 
133
 
-
 
134
// Partition Types:
-
 
135
#define PART_TYPE_UNKNOWN                       0x00
-
 
136
#define PART_TYPE_FAT12                         0x01
-
 
137
#define PART_TYPE_XENIX                         0x02
-
 
138
#define PART_TYPE_FAT16_ST_32_MB        0x04
-
 
139
#define PART_TYPE_EXTDOS                        0x05
-
 
140
#define PART_TYPE_FAT16_LT_32_MB        0x06
-
 
141
#define PART_TYPE_NTFS                          0x07
-
 
142
#define PART_TYPE_FAT32                         0x0B
-
 
143
#define PART_TYPE_FAT32LBA                      0x0C
-
 
144
#define PART_TYPE_FAT16LBA                      0x0E
-
 
145
#define PART_TYPE_EXTDOSLBA                     0x0F
-
 
146
#define PART_TYPE_EISA                          0x12
-
 
147
#define PART_TYPE_ONTRACK                       0x33
-
 
148
#define PART_TYPE_NOVELL                        0x40
-
 
149
#define PART_TYPE_DYNAMIC                       0x42
-
 
150
#define PART_TYPE_PCIX                          0x4B
-
 
151
#define PART_TYPE_LINUX_SWAP            0x82
-
 
152
#define PART_TYPE_LINUX_NATIVE          0x83
-
 
153
#define PART_TYPE_LINUX_LVM                     0x8E
-
 
154
#define PART_TYPE_PHOENIXSAVE           0xA0
-
 
155
#define PART_TYPE_FREEBSD                       0xA5
-
 
156
#define PART_TYPE_OPENBSD                       0xA6
-
 
157
#define PART_TYPE_NETNBSD                       0xA9
-
 
158
#define PART_TYPE_CPM                           0xDB
-
 
159
#define PART_TYPE_DBFS                          0xE0
-
 
160
#define PART_TYPE_BBT                           0xFF
-
 
161
 
98
//________________________________________________________________________________________________________________________________________
162
 
-
 
163
/*
-
 
164
________________________________________________________________________________________________________________________________________
-
 
165
 
-
 
166
        Structure of the MasterBootRecord                      
-
 
167
________________________________________________________________________________________________________________________________________
-
 
168
 
99
// 
169
        Master Boot Record is 512 bytes long
-
 
170
        The Master Boot Record is the same for pretty much all Operating Systems.
-
 
171
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
-
 
172
*/
-
 
173
typedef struct
-
 
174
{
-
 
175
        u8                              ExecutableCode[446];    // 446 bytes for machine start code     
-
 
176
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1                                       
-
 
177
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2                                       
-
 
178
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3                                       
-
 
179
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4                                       
-
 
180
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)   
-
 
181
} __attribute__((packed)) MBR_Entry_t;
-
 
182
 
100
// Global variables needed for read- or write-acces to the FAT16- filesystem.
183
 
101
//                              
184
/*
-
 
185
________________________________________________________________________________________________________________________________________
-
 
186
 
-
 
187
        Structure of the VolumeBootRecord                      
102
//________________________________________________________________________________________________________________________________________
188
________________________________________________________________________________________________________________________________________
-
 
189
 
-
 
190
        The Volume Boot Record is 512 bytes long
-
 
191
        This information is located in the first sector of every partition.
-
 
192
*/
-
 
193
typedef struct
-
 
194
{
-
 
195
        u8  JumpCode[3];                        // Jump Code + NOP
-
 
196
        s8  OEMName[8];                         // OEM Name             
103
 
197
        u16 BytesPerSector;                     // Bytes Per Sector
-
 
198
        u8  SectorsPerCluster;          // Sectors Per Cluster
104
u8              SectorsPerCluster               = 0;                                                                                    // how many sectors does a cluster contain?
199
        u16 ReservedSectors;            // Reserved Sectors
105
u8              FatCopies                               = 0;                                                                                    // Numbers of copies of the FAT
200
        u8  NoFATCopies;                        // Number of Copies of FAT
106
u16             PossibleRootEntries     = 0;                                                                                    // Possible number of entries in the root directory.
201
        u16 MaxRootEntries;                     // Maximum Root Directory Entries 
-
 
202
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
-
 
203
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
-
 
204
        u16 SectorsPerFAT;                      // Sectors Per FAT
-
 
205
        u16 SectorsPerTrack;            // Sectors Per Track
107
u16             SectorsPerFat                   = 0;                                                                                    // how many sectors does a fat16 contain?
206
        u16 NoHeads;                            // Number of Heads
108
u32             ReservedSectors                 = 0;                                                                                    // Sectors reserved by the filesystem.
207
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
-
 
208
        u32 NoSectors;                          // Number of Sectors in Partition
-
 
209
        u16     DriveNo;                                // Logical Drive Number of Partition
109
u32             FirstPartitionSector    = 0;                                                                                    // Distance in sectors between the first partition and the master bootrecord.
210
        u8  ExtendedSig;                        // Extended Signature (0x29)
110
u32             FileAllocationTable     = 0;                                                                                    // pointer to the first FAT
211
        u32 SerialNo;                           // Serial Number of the Partition
-
 
212
        s8  VolumeName[11];                     // Volume Name of the Partititon
111
u32             RootDirectory                   = 0;                                                                                    // Pointer to the rootdirectory of the first partition.
213
        s8  FATName[8];                         // FAT Name (FAT16)
112
u32             FirstDataCluster                = 0;                                                                                    // Pointer to the first cluster containing data (cluster0).
214
        u8  ExecutableCode[446];        // 446 bytes for machine start code     
-
 
215
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)        
-
 
216
} __attribute__((packed)) VBR_Entry_t;
-
 
217
 
-
 
218
 
-
 
219
 
-
 
220
/*
113
u32             CWD                                             = 0;                                                                                    // Pointer startcluster to the current working directory
221
________________________________________________________________________________________________________________________________________
-
 
222
 
-
 
223
        Structure of an directory entry                
114
 
224
________________________________________________________________________________________________________________________________________
-
 
225
 
-
 
226
        Directory entry is 32 bytes.
-
 
227
*/
-
 
228
typedef struct
-
 
229
{
-
 
230
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
-
 
231
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
-
 
232
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
115
 
233
        u8      Reserved[10];                           // reserved bytes within the directory entry.
116
struct DirEntry         *DirectoryEntry;                                                                                        // Pointer to an entry of the directory.
234
        u32 DateTime;                                   // date and time of last write access to the file or directory.
-
 
235
        u16 StartCluster;                               // first cluster of the file or directory.
-
 
236
        u32 Size;                                               // size of the file or directory in bytes.
-
 
237
}  __attribute__((packed)) DirEntry_t;
-
 
238
 
-
 
239
#define SLOT_EMPTY              0x00    // slot has never been used
-
 
240
#define SLOT_E5                 0x05    // the real value is 0xe5
117
struct FatEntry         *Fat;                                                                                                           // Pointer to an entry of the fat (next clusterposition).
241
#define SLOT_DELETED            0xE5    // file in this slot deleted
-
 
242
 
-
 
243
#define ATTR_NONE               0x00    // normal file
-
 
244
#define ATTR_READONLY           0x01    // file is readonly
-
 
245
#define ATTR_HIDDEN                     0x02    // file is hidden
-
 
246
#define ATTR_SYSTEM                     0x04    // file is a system file
118
 
247
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
-
 
248
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
-
 
249
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
119
File FilePointer[__MAX_FILES_USED];                                                                                             // Allocate Memmoryspace for each filepointer used.
250
#define ATTR_ARCHIVE            0x20    // file is new or modified
120
 
251
 
-
 
252
 
121
 
253
/*
-
 
254
________________________________________________________________________________________________________________________________________
122
//________________________________________________________________________________________________________________________________________
255
 
-
 
256
        Structure of an entry within the fileallocationtable.                  
123
// Funtion:     InitFat16(void);
257
________________________________________________________________________________________________________________________________________
-
 
258
*/
-
 
259
typedef struct
-
 
260
{
-
 
261
        u16  NextCluster;                               // the next cluster of the file.
-
 
262
} __attribute__((packed)) Fat16Entry_t;
-
 
263
 
-
 
264
// secial fat entries
-
 
265
#define FAT16_CLUSTER_FREE                      0x0000
-
 
266
#define FAT16_CLUSTER_RESERVED          0x0001
-
 
267
#define FAT16_CLUSTER_USED_MIN          0x0002
-
 
268
#define FAT16_CLUSTER_USED_MAX          0xFFEF
-
 
269
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
-
 
270
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
-
 
271
#define FAT16_CLUSTER_BAD                       0xFFF7
-
 
272
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
-
 
273
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
-
 
274
 
-
 
275
/*****************************************************************************************************************************************/
124
// 
276
/*                                                                                                                                                                                                                                                                               */
-
 
277
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
-
 
278
/*                                                                                                                                                                                                                                                                               */
-
 
279
/*****************************************************************************************************************************************/
125
// Description: This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdirectory
280
 
-
 
281
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
-
 
282
#define DIRENTRY_SIZE                           32              //bytes
-
 
283
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
-
 
284
#define FAT16_BYTES                                     2
-
 
285
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
-
 
286
 
-
 
287
#define FSTATE_UNUSED   0                                       
-
 
288
#define FSTATE_USED             1
-
 
289
 
126
//                              and stores the information in global variables.
290
typedef struct
-
 
291
{
-
 
292
        u8      IsValid;                                // 0 means invalid, else valid
-
 
293
        u8      SectorsPerCluster;              // how many sectors does a cluster contain?
-
 
294
        u8      FatCopies;                              // Numbers of copies of the FAT
-
 
295
        u16     MaxRootEntries;                 // Possible number of entries in the root directory.
-
 
296
        u16     SectorsPerFat;                  // how many sectors does a fat16 contain?
-
 
297
        u32 FirstFatSector;                     // sector of the start of the fat
-
 
298
        u32 FirstRootDirSector;         // sector of the rootdirectory
-
 
299
        u32 FirstDataSector;            // sector of the first cluster containing data (cluster2).
-
 
300
        u32 LastDataSector;                     // the last data sector of the partition
-
 
301
} Partition_t;
-
 
302
 
-
 
303
Partition_t     Partition;                                      // Structure holds partition information
-
 
304
 
-
 
305
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
-
 
306
 
-
 
307
 
-
 
308
/****************************************************************************************************************************************/
-
 
309
/*      Function:               FileDateTime(DateTime_t *);                                                                                                                                                                                     */
127
//
310
/*                                                                                                                                                                                                                                                                              */
-
 
311
/*      Description:    This function calculates the DOS date time from a pointer to a time structure.                                                                          */
-
 
312
/*                                                                                                                                                                                                                                                                              */
128
// Returnvalue: The function returns "0" if the filesystem could not be initialized because no partition was found on the volume. 
313
/*      Returnvalue:    Returns the DOS date time.                                                                                                                                                                                      */
129
//________________________________________________________________________________________________________________________________________
314
/****************************************************************************************************************************************/
-
 
315
 
-
 
316
u32 FileDateTime(DateTime_t * pTimeStruct)
130
 
317
{
-
 
318
        u32 datetime = 0;
-
 
319
        if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime;
-
 
320
 
-
 
321
        datetime |= (0x0000007FL & (u32)(pTimeStruct->Year - 1980))<<25; // set year
-
 
322
        datetime |= (0x0000000FL & (u32)(pTimeStruct->Month))<<21; // set month
-
 
323
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Day))<<16;
-
 
324
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Hour))<<11;
-
 
325
        datetime |= (0x0000003FL & (u32)(pTimeStruct->Min))<<5;
-
 
326
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Sec/2));
-
 
327
        return datetime;
-
 
328
}
-
 
329
 
-
 
330
 
-
 
331
/****************************************************************************************************************************************/
-
 
332
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
-
 
333
/*                                                                                                                                                                                                                                                                              */
-
 
334
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
-
 
335
/*                                                                                                                                                                                                                                                                              */
-
 
336
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
-
 
337
/****************************************************************************************************************************************/
-
 
338
File_t * LockFilePointer(void)
-
 
339
{
-
 
340
        u8 i;
-
 
341
        File_t * File = 0;
131
u8 InitFat16(void)
342
        for(i = 0; i < FILE_MAX_OPEN; i++)
132
{      
-
 
133
        u8 retvalue = 0;
-
 
134
    u8  cnt     = 0;
-
 
135
        struct VBR_Entry *VBR;                                                                                                          // Pointer to the VolumeBootRecord.
343
        {
136
        struct MBR_Entry *MBR;                                                                                                          // Pointer to the masterbootrecord.     
-
 
137
        File *file;
-
 
138
 
-
 
139
        for(cnt=0;cnt<__MAX_FILES_USED;cnt++)
344
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one                                                                                  
-
 
345
                {
140
        {
346
                        File = &FilePointer[i];                                         // set pointer to that entry             
-
 
347
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
141
                FilePointer[cnt].state = _UNUSED;                                                                               // declare the filepointers as unused.
348
                        break;
142
        }
-
 
143
       
-
 
144
        file = &FilePointer[0];
-
 
145
 
-
 
146
        SerialPutString("\n\rFAT16 init...");
-
 
147
        while((SDC_Init() != SD_SUCCESS) && (cnt++<100));
-
 
148
 
-
 
149
        if(cnt <100)                                                                                                                            // sdcard initialised succesfully
-
 
150
        {
-
 
151
                SDC_GetSector((u32)_MBR_SECTOR,file->buffer);                                                   // Read the MasterBootRecord from mmc.
-
 
152
                MBR = (struct MBR_Entry *) file->buffer;
-
 
153
                FirstPartitionSector = MBR->PartitionEntry1.NoSectorsBeforePartition;
-
 
154
                if((MBR->PartitionEntry1.Type == _FAT16_32_MB_BIOS_Extension) ||
-
 
155
                   (MBR->PartitionEntry1.Type == _FAT16_ST_32_MB) ||
-
 
156
                   (MBR->PartitionEntry1.Type == _FAT16_LT_32_MB))
-
 
157
                {
-
 
158
                        SDC_GetSector(FirstPartitionSector,file->buffer);                                       // Read the volume bootrecord from mmc. 
-
 
159
       
-
 
160
                        VBR = (struct VBR_Entry *) file->buffer;                                                        // Enter the VBR using the structure VBR_Entry.
-
 
161
                        SectorsPerCluster       = VBR->SectorsPerCluster;                                               // Number of sectors per cluster. Depends on the memorysize of the sd-card.
-
 
162
                        FatCopies                       = VBR->NoFATCopies;                                                             // Number of fatcopies.
-
 
163
                        PossibleRootEntries = VBR->MaxRootEntries;                                                      // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
-
 
164
                        SectorsPerFat           = VBR->SectorsPerFAT;                                                   // The number of sectors per FAT.
-
 
165
                        ReservedSectors         = VBR->ReservedSectors;                                                 // calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster.
-
 
166
 
-
 
167
                        FileAllocationTable     =   (u32)(FirstPartitionSector + (u32)ReservedSectors);                                                 // Calculate the position of the FileAllocationTable.
-
 
168
                        RootDirectory           =   (u32)((u32)FileAllocationTable + (u32)((u32)SectorsPerFat*(u32)FatCopies)); // Calculate the position of the Rootdirectory.
-
 
169
                        FirstDataCluster        =   (u32)((u32)RootDirectory + ((u32)(PossibleRootEntries>>4)));                                        // Calculate the position of the first datacluster.
-
 
170
                        CWD                                     =       RootDirectory;                                                                                                                                  // The actual directory is the rootdirectory.
-
 
171
                        retvalue = 1;
-
 
172
                        SerialPutString("\n\rfilesystem ok");                                  
-
 
173
                        str_Volume.state = INITIALIZED;
349
                }
174
                }
350
        }
175
                else
-
 
176
                {
-
 
177
                        str_Volume.state = NOT_INITIALIZED;
-
 
178
                        SerialPutString("\n\rfilesystem nok");         
351
        return(File);
-
 
352
}
-
 
353
 
-
 
354
/****************************************************************************************************************************************/
-
 
355
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
-
 
356
/*                                                                                                                                                                                                                                                                              */
-
 
357
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
-
 
358
/*                                                                                                                                                                                                                                                                              */
-
 
359
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
-
 
360
/****************************************************************************************************************************************/
-
 
361
u8 UnlockFilePointer(File_t * file)
-
 
362
{
-
 
363
        u8 cnt;
-
 
364
        if(file == NULL) return(0);
-
 
365
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
-
 
366
        {
-
 
367
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
-
 
368
                {
-
 
369
                        file->State = FSTATE_UNUSED;                                                                                                   
-
 
370
                        file->FirstSectorOfFirstCluster = 0;                    // Sectorpointer to the first sector of the first datacluster of the file. 
-
 
371
                        file->FirstSectorOfCurrCluster  = 0;
-
 
372
                        file->SectorOfCurrCluster               = 0;                    // Pointer to the cluster which is edited at the moment.
-
 
373
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
-
 
374
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
-
 
375
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
-
 
376
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
-
 
377
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
-
 
378
                        file->SectorInCache                     = 0;                    // the last sector read, wich is still in the sectorbuffer.
-
 
379
                        file->DirectorySector                   = 0;                    // the sectorposition where the directoryentry has been made.
-
 
380
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
-
 
381
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
-
 
382
                        file = NULL;
179
                }
383
                        return(1);
-
 
384
                }
180
        }
385
        }
181
        return(retvalue);      
386
        return(0);
182
}
387
}
183
 
388
 
184
//________________________________________________________________________________________________________________________________________
-
 
-
 
389
/****************************************************************************************************************************************/
185
// Funtion:     File * fopen_(u8*, u8 *);
390
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
-
 
391
/*                                                                                                                                                                                                                                                                              */
186
// 
392
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
187
// Description: This function looks for the file to be opened in the directory specified by the variable "CWD" of the drive. 
-
 
188
//                              If the file was found this function returns a filepoiner to the opened file otherwise NULL//                            
393
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
189
//
-
 
-
 
394
/*                                      The subpath is the pointer to the remaining substring if the filepath                                                                                           */
190
//      Return:         Pointer to the opened file or NULL
395
/*                                                                                                                                                                                                                                                                              */
191
//                              
-
 
192
//________________________________________________________________________________________________________________________________________
396
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
193
 
397
/****************************************************************************************************************************************/
-
 
398
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
194
File * fopen_(s8 *fname, s8 mode)
399
{
195
{
-
 
196
        File *file;
400
        s8* subpath = NULL;
-
 
401
        u8 readpointer  = 0;
-
 
402
        u8 writepointer = 0;
-
 
403
 
-
 
404
        // search subpath from beginning of filepath                                    
197
       
405
        subpath = NULL;
198
        file = ReserveFilePointer();                                                                                                    // reserve a filepointer.       
406
        readpointer     = 0;
199
       
407
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
-
 
408
        while(subpath == NULL)  // search the filepath until a subpath was found.       
-
 
409
        {
-
 
410
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached 
-
 
411
                {      
-
 
412
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
-
 
413
                }
-
 
414
                readpointer++;
-
 
415
        }
-
 
416
 
-
 
417
        // clear dirname with spaces
-
 
418
        dirname[11] = 0; // terminate dirname
-
 
419
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
-
 
420
        writepointer = 0;
-
 
421
        // start seperating the dirname from the filepath.
200
        if(file != NULL)                                                                                                                                // A free filepointer was found.
422
        readpointer = 0;
-
 
423
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
201
        {
424
        while( &filepath[readpointer] < subpath)
202
                file->mode      = mode;                                                                                                                 // mode of fileoperation (read,write)
425
        {
203
 
-
 
204
                if(SeekFileInDirectory(fname, file))                                                                            // if file was found
426
                if(writepointer >= 11) return(NULL);            // dirname to long
-
 
427
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
205
                {
428
                {
206
                        SerialPutString("ok");
429
                        if(writepointer <= 8)
-
 
430
                        {
207
                        if(mode == 'a')                                                                                                                 // open existing file for writing (append data at the end of the file)
431
                                readpointer++;                                          // next character in filename
208
                        {      
432
                                writepointer = 8;                                       // jump to start of extension
209
                                fseek_(file, 0, SEEK_END);                                                                                      // fseek points to the end of the file
433
                        }
210
                        }
434
                        else return(NULL);                                              // dirbasename to long                                                          
211
                }              
435
                }
212
                else
436
                else
213
                {
437
                {
214
                        if((mode == 'a') || (mode == 'w'))                                                                              // specified file doesn't exist so create new file for writing data.
-
 
215
                        {      
-
 
216
                                if(CreateFileInDirectory(fname,file))                                                           // Could an entry for the new file in the rootdirectory be created?
438
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
217
                                {
439
                        {
218
                                        return(file);
440
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
219
                                }      
441
                        }
220
                                else
442
                        else
221
                                {
443
                        {
222
                                        FreeFilePointer(file);                                                                              // free the filepointer.
444
                                dirname[writepointer] = filepath[readpointer];
223
                                        file = NULL;
-
 
224
                                }
-
 
225
                        }
-
 
226
            else                                                                    // file with mode 'r' not found
-
 
227
            {
-
 
228
                FreeFilePointer(file);                                                                                          // free the filepointer.
-
 
229
                file = NULL;                                                        // file not found
-
 
230
            }
445
                        }      
-
 
446
                        readpointer++;
-
 
447
                        writepointer++;
231
                }
448
                }
232
        }
449
        }
233
        return(file);
450
        return(subpath);       
234
}
451
}
235
 
452
 
-
 
453
 
-
 
454
/**************************************************************************************************************************************+*/
-
 
455
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
-
 
456
/*                                                                                                                                                                                                                                                                              */
-
 
457
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
-
 
458
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
-
 
459
/*                                                                                                                                                                                                                                                                              */
-
 
460
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
-
 
461
/****************************************************************************************************************************************/
-
 
462
u32     Fat16ClusterToSector(u16 cluster)
-
 
463
{
-
 
464
        if(!Partition.IsValid) return 0;
-
 
465
        if (cluster < 2) cluster = 2; // the 0. and 1. cluster in the fat are used for the media descriptor 
-
 
466
        return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
236
 
467
}
-
 
468
 
237
 
469
/****************************************************************************************************************************************/
238
//________________________________________________________________________________________________________________________________________
-
 
239
// Funtion:     fflush_(File *file);
470
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
240
// 
-
 
-
 
471
/*                                                                                                                                                                                                                                                                              */
-
 
472
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
-
 
473
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
241
// Description: This function writes the data already in the buffer but not yet written to the file. 
474
/*                                                                                                                                                                                                                                                                              */
242
//                              
-
 
243
//________________________________________________________________________________________________________________________________________
475
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
244
 
476
/****************************************************************************************************************************************/
245
s16     fflush_(File *file)
477
u16     SectorToFat16Cluster(u32 sector)
-
 
478
{
246
{
479
        if(!Partition.IsValid) return 0;
-
 
480
        return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
-
 
481
}
-
 
482
 
-
 
483
 
-
 
484
/****************************************************************************************************************************************/
-
 
485
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
-
 
486
/*                                                                                                                                                                                                                                                                              */
-
 
487
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
-
 
488
/*                                                                                                                                                                                                                                                                              */
-
 
489
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
-
 
490
/****************************************************************************************************************************************/
247
        u16 time=0;
491
u8 Fat16_Deinit(void)
-
 
492
{
248
        u16 date=0;
493
        s16 returnvalue = 0;
249
 
494
        u8 cnt;
250
                       
495
        // declare the filepointers as unused.
251
        if(file && ((file->mode =='a') || (file->mode =='w')))
496
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
252
        {
497
        {
253
                if(file->byte_index > 0)                                                                                                                        // has data been added to the file?             
-
 
254
                {
-
 
255
                        SDC_PutSector((u32)(file->cluster_pointer + file->sector_index),file->buffer);// save the data still in the buffer      
-
 
256
                }      
-
 
257
                SDC_GetSector((u32)file->directory_sector,file->buffer);                                                        // read the directoryentry for this file.
-
 
258
                DirectoryEntry = (struct DirEntry *)file->buffer;
-
 
-
 
498
                if(FilePointer[cnt].State == FSTATE_USED)
259
                DirectoryEntry[file->directory_index].size = (u32) file->filesize;
499
                {
-
 
500
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
-
 
501
                }
260
                DirectoryEntry[file->directory_index].time = (u16) time;
502
                                                               
261
                DirectoryEntry[file->directory_index].date = (u16) date;
503
        }
262
                SDC_PutSector((u32)file->directory_sector,file->buffer);
504
        SDC_Deinit();                   // uninitialize interface to sd-card
263
        }
505
        Partition.IsValid = 0;  // mark data in partition structure as invalid
264
        return(0);
-
 
-
 
506
        return(returnvalue);
265
}
507
}
-
 
508
 
266
 
509
/****************************************************************************************************************************************/
-
 
510
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
267
//________________________________________________________________________________________________________________________________________
511
/*                                                                                                                                                                                                                                                                          */
268
// Funtion:     fclose_(File *file);
-
 
269
// 
512
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
270
// Description: This function closes the open file by writing the remaining data from the buffer to the device and entering the filesize 
513
/*                                      and stores the information in global variables.                                                                                                                                     */
-
 
514
/*                                                                                                                                                                                                                                                                          */
-
 
515
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
-
 
516
/****************************************************************************************************************************************/
-
 
517
u8 Fat16_Init(void)
-
 
518
{      
-
 
519
    u8  cnt     = 0;
-
 
520
        u32     partitionfirstsector;
271
//                              in the directory entry.
521
        VBR_Entry_t *VBR;              
-
 
522
        MBR_Entry_t *MBR;
-
 
523
        File_t *file;
-
 
524
        u8 result = 0;
272
//________________________________________________________________________________________________________________________________________
525
 
273
 
-
 
274
void fclose_(File *file)
-
 
275
{
526
        SerialPutString("\r\n FAT16 init...");
276
 
527
        Partition.IsValid = 0;
-
 
528
 
-
 
529
        // declare the filepointers as unused.
277
        if(file != NULL)
-
 
278
        {
530
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
279
                fflush_(file);                                                                                                                                          // save buffered data to the disk
-
 
280
        }
-
 
281
        FreeFilePointer(file);                                                                                                                                  // and free the filepointer.
-
 
282
}
-
 
283
 
-
 
284
//________________________________________________________________________________________________________________________________________
-
 
285
// Funtion:     u32 fread_(void *buffer, s32 size, s32 count, File *file);
-
 
286
// 
531
        {
287
// Description: This function reads count objects of the specified size from the actual position of the file to the specified buffer.
532
                FilePointer[cnt].State = FSTATE_UNUSED;                                        
288
//                              
533
        }
289
// Returnvalue: The function returns the number of objects (not bytes) read from the file.      
-
 
290
//                              
534
        // set current file pinter to first position in list
291
//________________________________________________________________________________________________________________________________________
535
        file = &FilePointer[0];                                                                        
292
 
536
       
293
u32 fread_(void *buffer, u32 size, u32 count, File *file)
-
 
294
{
537
        // try to initialise the sd-card.
-
 
538
        if(SD_SUCCESS != SDC_Init())                                                   
295
        u32 object_cnt  = 0;                                                                                                                    // count the number of objects read from the file.
539
        {  
-
 
540
                SerialPutString("SD-Card could not be initialized.");
296
        u32 object_size         = 0;                                                                                                            // count the number of bytes read from the actual object.
541
                result = 1;
-
 
542
                goto end;      
-
 
543
        }
-
 
544
 
-
 
545
        // SD-Card is initialized successfully
-
 
546
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
297
        u8 *buff_pnt    = 0;                                                                                                                    // a pointer to the actual bufferposition.
547
        {
298
        u8 success      = 1;                                                                                                                    // no error occured during read operation to the file.
548
                SerialPutString("Error reading the MBR.");
-
 
549
                result = 2;
-
 
550
                goto end;      
-
 
551
        }
299
       
552
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
-
 
553
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
-
 
554
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
300
        buff_pnt = (u8 *) buffer;                                                                                                               // cast the void pointer to an u8 *
555
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
301
       
556
        {
302
        while((object_cnt < count) && success)
557
                // get sector offset 1st partition
303
        {
-
 
304
                object_size = size;
558
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
-
 
559
                // Start of Partition is the Volume Boot Sector
305
                while((size > 0) && success)
560
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
306
                {
561
                {
307
                        *buff_pnt = (u8) fgetchar_(file);                                                                               // read a byte from the buffer to the opened file.
562
                        SerialPutString("Error reading the VBR.");
308
                        buff_pnt++;
-
 
309
                        size--;
-
 
310
                }
-
 
311
                if(success) object_cnt++;
-
 
312
        }              
-
 
313
       
563
                        result = 3;
314
        return(object_cnt);                                                                                                                             // return the number of objects succesfully read from the file
-
 
315
}
-
 
316
 
-
 
317
//________________________________________________________________________________________________________________________________________
564
                        goto end;      
318
// Funtion:     u32 fwrite_(void *buffer, s32 size, s32 count, File *file);
565
                }                      
319
// 
566
        }
-
 
567
        else  // maybe the medium has no partition assuming sector 0 is the vbr
-
 
568
        {
-
 
569
                partitionfirstsector = 0;
320
// Description: This function writes count objects of the specified size from the buffer to the actual positon within the file.
570
        }
321
//                              
571
       
322
// Returnvalue: The function returns the number of objects (not bytes) written to the file.     
572
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
323
//                              
-
 
324
//________________________________________________________________________________________________________________________________________
573
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
-
 
574
        {
-
 
575
                SerialPutString("VBR: Sector size not supported.");
-
 
576
                result = 4;
-
 
577
                goto end;      
-
 
578
        }
-
 
579
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
-
 
580
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
-
 
581
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
-
 
582
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
-
 
583
 
325
 
584
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
-
 
585
        // Calculate the position of the FileAllocationTable: 
326
u32 fwrite_(void *buffer, u32 size, u32 count, File *file)
586
        // Start + # of Reserved Sectors
-
 
587
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors)); 
327
{
588
        // Calculate the position of the Rootdirectory: 
-
 
589
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)                                                     
-
 
590
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
-
 
591
        // Calculate the position of the first datacluster:
328
        u32 object_cnt  = 0;                                                                                                                    // count the number of objects written to the file.
592
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)                
-
 
593
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
329
        u32 object_size         = 0;                                                                                                            // count the number of bytes written from the actual object.
594
        // Calculate the last data sector
330
        u8 *buff_pnt    = 0;                                                                                                                    // a pointer to the actual bufferposition.
595
        if(VBR->NoSectors == 0)
331
        u8 success      = 1;                                                                                                                    // no error occured during write operation to the file.
596
        {
332
       
597
                SerialPutString("VBR: Bad number of sectors.");
333
        buff_pnt = (u8 *) buffer;                                                                                                               // cast the void pointer to an u8 *
598
                result = 5;
-
 
599
                goto end;      
-
 
600
        }
-
 
601
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
334
       
602
        // check for FAT16 in VBR of first partition
-
 
603
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
-
 
604
        {
335
        while((object_cnt < count) && success)
605
                SerialPutString("VBR: Partition ist not FAT16 type.");
336
        {
-
 
337
                object_size = size;
-
 
338
                while((size > 0) && success)
-
 
339
                {
-
 
340
                        success = fputchar_(file, *buff_pnt);                                                                   // write a byte from the buffer to the opened file.
-
 
341
                        buff_pnt++;
-
 
342
                        size--;
-
 
343
                }
-
 
344
                if(success) object_cnt++;
-
 
-
 
606
                result = 6;
-
 
607
                goto end;
-
 
608
        }
-
 
609
        Partition.IsValid = 1; // mark data in partition structure as valid
-
 
610
        result = 0;
-
 
611
        end:
-
 
612
        if(result != 0) Fat16_Deinit();
345
        }              
613
        else SerialPutString("ok");
346
       
614
        return(result);
347
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
-
 
348
}                                                                                                                                                                       // (!!!!! objects and not bytes !!!!)
615
}
349
 
616
 
-
 
617
 
-
 
618
 
350
//________________________________________________________________________________________________________________________________________
619
/****************************************************************************************************************************************/
351
// Funtion:     s16 fseek_(File *, s32, s16)
620
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
352
// 
621
/*                                                                                                                                                                                                                                                                              */
353
// Description: This function sets the pointer of the stream relative to the position 
-
 
354
//                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END). 
-
 
355
//                              
622
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
356
//________________________________________________________________________________________________________________________________________
623
/*                                                                                                                                                                                                                                                                              */
357
 
624
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
358
s16 fseek_(File *file, s32 offset, s16 origin)
625
/****************************************************************************************************************************************/
-
 
626
u8 ClearCurrCluster(File_t * file)
359
{
627
{
360
        s32                     fposition       = 0;
-
 
361
        s16                     retvalue        = 1;
-
 
362
        u32     temp            = 0;
628
        u8 retvalue = 1;
363
       
629
        u32 i;
364
//......................................................
630
       
-
 
631
        if((!Partition.IsValid) || (file == NULL)) return(0);
-
 
632
 
365
        if(origin == SEEK_SET)                                                                                                          // Fileposition relative to the beginning of the file.
633
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
366
        {
-
 
367
                fposition = 0;
634
        for(i = 0; i < Partition.SectorsPerCluster; i++)
-
 
635
        {
-
 
636
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
-
 
637
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
-
 
638
                {
368
        }      
639
                        Fat16_Deinit();
369
//......................................................
640
                        retvalue = 0;
370
        else if(origin == SEEK_END)                                                                                                     // Fileposition relative to the end of the file.
-
 
371
        {
641
                }
372
                fposition  = (s32) file->filesize;
642
        }
373
        }      
-
 
-
 
643
        return(retvalue);      
-
 
644
}
-
 
645
 
-
 
646
/*****************************************************************************************************************************************/
-
 
647
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
-
 
648
/*                                                                                                                                                                                                                                                                               */
-
 
649
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
-
 
650
/*                                                                                                                                                                                                                                                                               */
-
 
651
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
-
 
652
/*****************************************************************************************************************************************/
-
 
653
u16 GetNextCluster(File_t * file)
-
 
654
{
-
 
655
        u16 cluster = 0;
374
//......................................................
656
        u32 fat_byte_offset, sector, byte;
-
 
657
        Fat16Entry_t * fat;
-
 
658
       
-
 
659
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
-
 
660
        // if sector is within the data area
-
 
661
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
-
 
662
        {
-
 
663
                // determine current file cluster
-
 
664
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
-
 
665
                // calculate byte offset in the fat for corresponding entry
-
 
666
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
-
 
667
                // calculate the sector that contains the current cluster within the fat
-
 
668
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
-
 
669
                // calculate byte offset of the current cluster within that fat sector
375
        else if(origin == SEEK_CUR)                                                                                                     // Fileposition relative to the current position of the file.
670
                byte = fat_byte_offset % BYTES_PER_SECTOR;
376
        {
-
 
377
                fposition = file->fileposition;
-
 
378
        }      
-
 
379
 
671
                // read this sector to the file cache
380
        fposition += offset;
672
                if(file->SectorInCache != sector)
381
 
673
                {
382
        if((fposition >= 0) && (fposition <= (s32)file->filesize))                              // is the pointer still within the file?
674
                        file->SectorInCache = sector;                                           // update sector stored in buffer
383
        {
675
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
384
                retvalue                                = 0;
676
                        {
385
                file->sector_index              = 0;
677
                                Fat16_Deinit();
386
                file->byte_index                = 0;
678
                                return (cluster);
387
                file->fileposition              = 0;
679
                        }              
388
                file->cluster_pointer   = file->start_cluster;
680
                }
389
               
681
                // read the next cluster from cache
390
                while(file->fileposition < fposition)
682
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
391
                {
683
                cluster = fat->NextCluster;
392
                        file->fileposition++;                                                                          
684
                // if last cluster fat entry 
393
                        if(file->byte_index < 511)                                                                     
685
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
394
                        {
686
                {
395
                                file->byte_index++;
687
                         cluster = 0;
396
                        }
688
                }
397
                        else
689
                else
398
                        {
690
                {
399
                                file->byte_index=0;                                                                                             // reading at the beginning of new sector.
-
 
400
                                file->sector_index++;                                                                                   // continue reading in next sector
691
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
401
                                if(file->sector_index >= SectorsPerCluster)                                     // When end of cluster is reached, the next datacluster has to be searched in the FAT.
-
 
402
                                {
-
 
403
                                        if(file->fileposition < fposition)
692
                        file->SectorOfCurrCluster = 0;
404
                                        {
-
 
405
                                                file->sector_index = 0;                                                                 // start reading new cluster at first sector of the cluster.
-
 
406
                                                GetNextCluster(file);                                                                   // Sets the clusterpointer of the file to the next datacluster.
-
 
407
                                        }
-
 
408
                                }
-
 
409
                        }      
-
 
410
                }
-
 
411
                if(file->byte_index)                           
693
                        file->ByteOfCurrSector = 0;
412
                {
-
 
413
                        temp = (u32)((u32)file->cluster_pointer + (u32)file->sector_index);                    
-
 
414
                        SDC_GetSector((u32)temp,file->buffer);                                                          // FileBuffer will be written at once at the end of the cluster and has to be updated.                                          
-
 
415
                }
694
                }
416
        }      
695
        }      
417
        return(retvalue);
696
        return(cluster);
418
}
697
}
419
 
-
 
420
//________________________________________________________________________________________________________________________________________
-
 
421
// Funtion:     fgetchar_(File *file);
-
 
422
// 
-
 
423
// Description: This function reads and returns one character from the specified file. 
-
 
424
//                              
-
 
425
// Returnvalue: The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.
-
 
-
 
698
 
-
 
699
 
-
 
700
/****************************************************************************************************************************************/
-
 
701
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
-
 
702
/*                                                                                                                                                                                                                                                                              */
-
 
703
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
-
 
704
/*                                                                                                                                                                                                                                                                              */
426
//________________________________________________________________________________________________________________________________________
705
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
427
 
706
/****************************************************************************************************************************************/
-
 
707
u16 FindNextFreeCluster(File_t *file)
428
s16 fgetchar_(File *file)
708
{
-
 
709
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
-
 
710
        u32     curr_sector;                            // current sector
429
{      
711
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
430
        s16 c = EOF;
-
 
431
        u32 temp1;
-
 
432
       
-
 
433
        if(((file->fileposition)+1) < file->filesize)                                                           // wen the end of the file is not reached, get the next character.
712
        u16     free_cluster    = 0;            // next free cluster number.
434
        {
713
        Fat16Entry_t * fat;
435
                temp1  = (u32)file->cluster_pointer;                                                                    // calculate the adress of the next character to be read.
-
 
436
                temp1 += (u32)file->sector_index;                      
-
 
437
       
-
 
438
                if(file->sector_in_buffer != temp1)                                                                     // Has the content of the buffer been modified and has to be updated?
-
 
439
                {
-
 
440
                        SDC_GetSector((u32)temp1,file->buffer);                                                 // Read the calculated cluster.                 
-
 
441
                        file->sector_in_buffer = (u32)temp1;
-
 
442
                }      
-
 
443
                c = (s16) file->buffer[file->byte_index];
-
 
444
                file->fileposition++;
714
       
445
       
715
        if((!Partition.IsValid) || (file == NULL)) return(0);
446
                if(file->byte_index < 511)                                                                                              // continue reading from this sector until the end of the sector is reached.
-
 
447
                {
716
 
448
                        file->byte_index++;
717
        // start searching for an empty cluster at the beginning of the fat.
449
                }
718
        fat_sector = 0;
450
                else                                                                                                                                    // has the end of an sector been reached->
719
        do     
451
                {
720
        {
452
                        file->byte_index=0;                                                                                                     // continue reading at the beginning -
-
 
453
                        file->sector_index++;                                                                                           // of new sector.
-
 
454
                        if(file->sector_index >= SectorsPerCluster)                                             // When the end of an cluster is reached, the next datacluster has to be searched in the FAT.
721
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
455
                        {
-
 
456
                                file->sector_index = 0;                                                                                 // start reading new cluster at first sector of the cluster.
-
 
457
                                GetNextCluster(file);                                                                                   // Sets the clusterpointer of the file to the next datacluster.
722
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
458
                        }
723
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
459
                }
-
 
460
        }
-
 
461
        return(c);
-
 
462
}
-
 
463
 
-
 
464
//________________________________________________________________________________________________________________________________________
724
                {
465
// Funtion:     fputchar_(File *file, s8 *);
-
 
466
// 
725
                        Fat16_Deinit();
467
// Description: This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries. 
726
                        return(free_cluster);
468
//                              
-
 
469
// Returnvalue: The function returns a value of 0 if the data could not be written.
-
 
470
//________________________________________________________________________________________________________________________________________
-
 
471
 
727
                }
472
u8 fputchar_(File *file,s8 c)
728
 
473
{      
-
 
474
        u32 ul_temp  = 0;
729
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
475
        u8 retvalue = 1;
-
 
476
       
-
 
477
    if(file->sector_index >= SectorsPerCluster)                                                         // if end of the cluster is reached, find next free cluster
-
 
478
        {
-
 
479
                file->sector_index = 0;
-
 
480
                if(!AppendCluster(file)) retvalue = 0;                                                                  // append a new and free cluster at the end of the file.
-
 
481
        }
730
 
482
 
731
                for(fat_entry = 0; fat_entry < FAT16_ENTRIES_PER_SECTOR; fat_entry++)                                           // look for an free cluster at all entries in this sector of the fat. 
-
 
732
                {
483
        file->buffer[file->byte_index] = c;                                                                             // write databyte into the buffer. The byte will be written to the device at once
733
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
484
        if(file->filesize == file->fileposition) file->filesize++;                                      // a character has been written to the file so the size is inkremented but only when the character has been added at the end of the file.
734
                        {                              
485
        file->fileposition++;                                                                                                           // the actual positon within the file. 
-
 
486
                                                                                                                                                                // if the buffer contains the complete sectordata.
-
 
487
        if(file->byte_index < 511)                                                                                                      // if the end of this sector is not reached yet
-
 
488
        {
-
 
489
                file->byte_index++;                                                                                                             // the next byte will be written to the next byteposition in this sector.
-
 
490
        }
-
 
491
        else                                                                                                                                            // otherwise the data in the sectorbuffer will be written to the device and the next sector will be selected.
-
 
492
        {
-
 
493
                ul_temp  = (u32)file->cluster_pointer;
735
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used 
494
                ul_temp += (u32)file->sector_index;
-
 
495
               
-
 
496
                SDC_PutSector((u32)ul_temp,file->buffer);
736
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
497
                file->byte_index=0;                                                                                                             // and the next byte will be written at the beginning of this new sector.
737
                                {
498
                file->sector_index++;
738
                                        Fat16_Deinit();
-
 
739
                                        return(free_cluster);
-
 
740
                                }
-
 
741
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);                          
499
                if(file->sector_index >= SectorsPerCluster)                                                     // if end of the cluster is reached, find next free cluster
742
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
500
                {
743
                        }
501
                        file->sector_index = 0;
-
 
502
                        if(!AppendCluster(file)) retvalue = 0;                                                          // append a new and free cluster at the end of the file.
-
 
503
                }
-
 
504
        }
-
 
505
        return(retvalue);
-
 
506
}
-
 
-
 
744
                }
-
 
745
                fat_sector++;                                                                                                   // continue the search in next fat sector
-
 
746
        // repeat until the end of the fat is  reached and no free cluster has been found so far                                                                        
-
 
747
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
-
 
748
        return(free_cluster);
-
 
749
}
-
 
750
 
507
 
751
 
508
//________________________________________________________________________________________________________________________________________
752
/****************************************************************************************************************************************************/
-
 
753
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
509
// Funtion:     fputs_(File *file, s8 *string);
754
/*                                                                                                                                                                                                                                                                                                      */
-
 
755
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
510
// 
756
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
511
// Description: This function writes a zero terminated string to the specified file.
757
/* Returnvalue: Is 1 if seek was successful                                                                                                                                                                                                                                                                     */
-
 
758
/****************************************************************************************************************************************************/
-
 
759
s16 fseek_(File_t *file, s32 offset, s16 origin)
-
 
760
{
-
 
761
        s32             fposition       = 0;
512
//                              
762
        s16     retvalue        = 1;
513
//________________________________________________________________________________________________________________________________________
763
       
-
 
764
        if((!Partition.IsValid) || (file == NULL)) return(0);
514
 
765
        switch(origin)
-
 
766
        {
515
u8 fputs_(File *file,s8 * string)
767
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
516
{
768
                        fposition = 0; 
517
        u8 i=0;
-
 
518
       
769
                        break;
519
        while(string[i] != 0)
-
 
520
        {
-
 
521
                fputchar_(file,string[i]);
-
 
522
                i++;
-
 
523
        }
-
 
524
        return(0);
770
                case SEEK_END:                          // Fileposition relative to the end of the file.
525
}
771
                        fposition = (s32)file->Size;
526
 
772
                        break;
-
 
773
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
527
//________________________________________________________________________________________________________________________________________
774
                default:
528
// Funtion:     s8 * fgets_(s8 *string, s16 count, File *file)
775
                        fposition = file->Position;
529
// 
-
 
530
// Description: This function reads a string from the file to the specifies string until EOF or end of line was detected.. 
776
                        break;
531
//              
777
        }
532
// Returnvalue: A pointer to the string or NULL if EOF was read from the file with no other characters before.
778
 
533
//________________________________________________________________________________________________________________________________________
779
        fposition += offset;
534
 
780
 
-
 
781
        if((fposition >= 0) && (fposition <= (s32)file->Size))          // is the pointer still within the file?
535
s8 * fgets_(s8 *string, s16 count, File *file)
782
        {
536
{
783
                // reset file position to start of the file
-
 
784
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
-
 
785
                file->SectorOfCurrCluster       = 0;
537
        s16 buff_pnt = 0;
786
                file->ByteOfCurrSector          = 0;
-
 
787
                file->Position                          = 0;
538
        s16 buff_tmp = 0;
788
 
-
 
789
                while(file->Position < fposition)       // repeat until the current position is less than target
539
        s8 *retvalue = 0;
790
                {
540
       
791
                        file->Position++;                               // increment file position
541
        retvalue = string;
792
                        file->ByteOfCurrSector++;               // next byte in current sector                                                                          
542
 
793
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)                                                                 
543
        while(count > 1)                                                                                                // read the count-1 characters from the file to the string.
-
 
-
 
794
                        {
544
        {
795
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
545
                buff_tmp = fgetchar_(file);                                                                     // read a character from the opened file.               
796
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
546
                if(buff_tmp == EOF)                                                                             // is the end of the file reached, terminate the string with zero.
-
 
547
                {
-
 
548
                        if(buff_pnt != 0)                                                                               // are there characters within the string?
-
 
549
                        {
-
 
550
                                break;
-
 
551
                        }
797
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
552
                        else
-
 
553
                        {
-
 
554
                                retvalue = NULL;                                                                        // first character read was EOF -> return(NULL);
-
 
555
                                break;
-
 
556
                        }
-
 
557
                }      
798
                                {
558
                else if(buff_tmp == 0x0A)                                                                       // lf detected.
799
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
559
                {              
800
                                        {
560
                        string[buff_pnt] = (s8) buff_tmp;                                               // add lf to the string.
801
                                                file->SectorOfCurrCluster = 0;         
561
                        buff_pnt++;
802
                                        }
562
                        break;
-
 
563
                }
-
 
564
                else
-
 
565
                {
-
 
566
                        string[buff_pnt] = (s8) buff_tmp;
-
 
567
                        count--;
-
 
568
                        buff_pnt++;
-
 
569
                }
-
 
570
        }
-
 
-
 
803
                                        else // the last cluster was allready reached
-
 
804
                                        {
-
 
805
                                                file->SectorOfCurrCluster--;                                                    // jump back to the ast sector in the last cluster
-
 
806
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
-
 
807
                                        }
-
 
808
                                }
571
        string[buff_pnt] = 0;                                                                                   // terminate string with zero
809
                        }      
572
        return(string);
810
                }      
573
}
811
        }
-
 
812
        if(file->Position == fposition) retvalue = 0;  
-
 
813
        return(retvalue);
-
 
814
}
-
 
815
 
-
 
816
 
574
 
817
/****************************************************************************************************************************************/
-
 
818
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
-
 
819
/*                                                                                                                                                                                                                                                                              */
-
 
820
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
-
 
821
/*                                                                                                                                                                                                                                                                              */
-
 
822
/****************************************************************************************************************************************/
-
 
823
u8 DeleteClusterChain(u16 StartCluster)
575
//________________________________________________________________________________________________________________________________________
824
{
-
 
825
        u16 cluster;                                                                                                           
576
// Funtion:     u8 fexist_(u8*);
826
        u32 fat_byte_offset, sector, byte;
577
// 
-
 
578
// Description: This function searches the specified file and returns 0 if the file was not found.
827
        Fat16Entry_t * fat;
579
//                              
-
 
580
//
-
 
581
//      Return:         0 = file does not exist
828
        u8 buffer[BYTES_PER_SECTOR];
-
 
829
        u32 sector_in_buffer = 0;
-
 
830
        u8 repeat = 0;
-
 
831
 
-
 
832
        if(!Partition.IsValid) return 0;
-
 
833
 
-
 
834
        cluster = StartCluster; // init chain trace
-
 
835
        // calculate byte offset in the fat for corresponding entry
-
 
836
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
-
 
837
        // calculate the sector that contains the current cluster within the fat
-
 
838
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
-
 
839
        // calculate byte offset of the current cluster within that fat sector
582
//                              1 = file exists
840
        byte = fat_byte_offset % BYTES_PER_SECTOR;
-
 
841
        do     
-
 
842
        {
-
 
843
                if(sector != sector_in_buffer)
-
 
844
                {
-
 
845
                        // read this sector to buffer
-
 
846
                        sector_in_buffer = sector;
-
 
847
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
-
 
848
                }              
-
 
849
                // read the next cluster from cache
-
 
850
                fat = (Fat16Entry_t *)(&(buffer[byte]));
583
//________________________________________________________________________________________________________________________________________
851
                cluster = fat->NextCluster;
-
 
852
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
-
 
853
                else repeat = 0;
-
 
854
 
584
 
855
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
585
u8 fexist_(s8 *fname)
-
 
586
{
-
 
587
        File *file;
-
 
588
 
-
 
589
        file = fopen_(fname,'r');                                                                               // try to open the specified file.
-
 
590
       
-
 
591
        if(file != NULL)
-
 
592
        {
-
 
593
                FreeFilePointer(file);                                                                          // Free the filepoint                                                                                           // free the filepointer
-
 
594
                return(1);                                                                                                      // file was found so return(1);
-
 
595
        }
-
 
596
        else
-
 
597
        {
-
 
598
                return(0);                                                                                                      // file not found return(0);
-
 
-
 
856
                // calculate byte offset in the fat for corresponding entry
-
 
857
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
-
 
858
                // calculate the sector that contains the current cluster within the fat
-
 
859
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
-
 
860
                // calculate byte offset of the current cluster within that fat sector
-
 
861
                byte = fat_byte_offset % BYTES_PER_SECTOR;
-
 
862
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
-
 
863
                if((sector != sector_in_buffer) || !repeat)
-
 
864
                {       // write sector in buffer
-
 
865
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;     
-
 
866
                }
-
 
867
        }
-
 
868
        while(repeat);
-
 
869
 
-
 
870
        return 1;
-
 
871
}
-
 
872
 
-
 
873
 
-
 
874
/****************************************************************************************************************************************/
-
 
875
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
-
 
876
/*                                                                                                                                                                                                                                                                              */
-
 
877
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
-
 
878
/*                                                                                                                                                                                                                                                                              */
599
        }
-
 
600
}
-
 
601
 
-
 
602
//________________________________________________________________________________________________________________________________________
879
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
603
// Funtion:     GetNextCluster(File *file);
-
 
604
// 
-
 
605
// Description: This function finds the next datacluster of the file specified with File *file. 
880
/****************************************************************************************************************************************/
606
//                              
-
 
607
// Returnvalue: The function returns "0" if the last cluster has already been reached.
-
 
608
//________________________________________________________________________________________________________________________________________
-
 
609
 
-
 
610
u16 GetNextCluster(File *file)
-
 
611
{
-
 
612
        u32 fat_pointer                 =       0;
-
 
613
        u32 fat_sector_offset   =       0;
-
 
614
        u32 ul_tmp                              =       0;
-
 
615
        u8 retvalue                             =       0;                                                                                                      // no new cluster found yet.
-
 
616
       
-
 
617
       
-
 
618
        if((file->cluster_pointer >= RootDirectory) && (file->cluster_pointer < (RootDirectory + 31)))
-
 
619
        {                                                                                                                                                               // Is the next cluster searched within the rootdirectory and available?
881
u16 AppendCluster(File_t *file)
620
                file->cluster_pointer++;                                                                                                        // the rootdirectory is a linear adress space of 32 clusters.
-
 
621
                retvalue = 1;                                                                                                                           // and the next cluster has been found.
-
 
622
        }
882
{
623
        else if(file->cluster_pointer > (RootDirectory + 31))                                                   // The specified cluster is within the FAT.
883
        u16 last_cluster, new_cluster = 0;                                                                                                             
624
        {
-
 
625
                fat_sector_offset   = ((file->cluster_pointer) - (FirstDataCluster));           // Calculate index of actual cluster within the FAT.
884
        u32 fat_byte_offset, sector, byte;
626
                fat_sector_offset  /= SectorsPerCluster;                                                                        // calculate the index of the actual sector within the FAT.                                     
885
        Fat16Entry_t * fat;
627
                fat_sector_offset  += 2;                                                                                                        // In Fat16 clusterpositions have an offset of two.     
886
       
628
                fat_pointer = (fat_sector_offset%0x100);                                                                        // Calculate the sector within the cluster.                                                                                                                             
-
 
629
                fat_sector_offset   = (fat_sector_offset>>8);                                                           // and the position within the sector.
887
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
630
 
-
 
631
                SDC_GetSector((u32)(FileAllocationTable + fat_sector_offset),file->buffer);    
-
 
632
                file->sector_in_buffer = (FileAllocationTable + fat_sector_offset);             // Mark that new sector has been read.
888
 
633
       
-
 
634
                ul_tmp  = (u32)file->buffer[((fat_pointer << 1)+1)];                                            // Read next sector information from calculated clusterposition.
889
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
635
                ul_tmp  = (ul_tmp << 8);
-
 
636
                ul_tmp |= (u32)file->buffer[(fat_pointer << 1)];    
890
        if(new_cluster)
637
                ul_tmp -=2;                                                                                                                                     // next datacluster is clusterposition in fat - 2.
-
 
638
                ul_tmp *= SectorsPerCluster;                                                                                            // calculate sectorposition of new cluster
-
 
639
                ul_tmp += FirstDataCluster;                                                                                                     // in relation to first datacluster of the disk.
-
 
640
       
891
        {       // A free cluster was found and can be added to the end of the file. 
641
                if(ul_tmp < 0xfff7)                                                                                                                     // has a new cluster been read or was the end of the fat reached?
-
 
642
                {
-
 
643
                        file->cluster_pointer = (u32) ul_tmp;                                                                   // continue reading the file at the beginning of new datacluster.
-
 
644
                        retvalue = 1;                                                                                                                   // a new cluster was found.
-
 
645
                }      
-
 
646
        }
-
 
647
        return(retvalue);
-
 
648
}
-
 
649
 
-
 
650
//________________________________________________________________________________________________________________________________________
-
 
651
// Funtion:     u16 FindNextFreeCluster(void)
-
 
652
// 
-
 
653
// Description: This function looks in the FAT to find the next free datacluster
-
 
654
//                              
-
 
655
// Returnvalue: The function returns the adress of the next free cluster found within the fAT.
-
 
656
//________________________________________________________________________________________________________________________________________
-
 
657
 
-
 
658
u16 FindNextFreeCluster(File *file)
-
 
659
{
-
 
660
        u32 fat_pointer                 =       0;                                                                                                      // Pointer to the first sector of the FAT.
-
 
661
        u32 ul_tmp                              =       0;                                                                                                      // temporary variable used to calculate a sectornumber.
-
 
662
        u16  fat_sector_offset  =       0;                                                                                                      // index to a sector within the FAT.
-
 
663
        u16  fat_entry                  =       0;                                                                                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
-
 
664
        u16  free_cluster                       =       0;                                                                                              // a pointer to the first sector of the next free cluster.
-
 
665
       
-
 
666
        fat_pointer = (u32) FileAllocationTable;                                                                                // start searching for empty cluster at the beginning of the fat.
892
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
667
                                                                                                                                                                        // if the end of the fat is not reached yet and no free cluster has been found
-
 
668
        while((fat_sector_offset < SectorsPerFat) && (!free_cluster))  
893
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster 
669
        {
894
                fat_byte_offset = ((u32)last_cluster)<<1;
-
 
895
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
-
 
896
                byte = fat_byte_offset % BYTES_PER_SECTOR;
-
 
897
 
-
 
898
                if(file->SectorInCache != sector)
-
 
899
                {
-
 
900
                        file->SectorInCache = sector;                                           // update sector stored in buffer
670
                ul_tmp = (u32) ((u32)fat_pointer + (u32)fat_sector_offset);
901
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
671
                SDC_GetSector((u32)ul_tmp,file->buffer);                                                                        // read next sector of FAT.
902
                        {
-
 
903
                                Fat16_Deinit();
672
                file->sector_in_buffer = ul_tmp;                                                                                        // remember the number of the sector in FileBuffer.
904
                                return(0);
673
                Fat = (struct FatEntry *)file->buffer;
-
 
674
                for(fat_entry=0;fat_entry<256;fat_entry++)                                                                      // look for an free cluster at all entries in this sector of the fat. 
905
                        }      
675
                {
-
 
-
 
906
                }                                            
676
                        if(Fat[fat_entry].next_cluster == 0x0000)                                                               // empty cluster found!!
907
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
677
                        {                              
908
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
678
                                Fat[fat_entry].next_cluster = 0xffff;                                                           // mark this fat-entry as used and save it to the device.
-
 
679
                                SDC_PutSector((u32)file->sector_in_buffer,file->buffer);
909
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
680
                                free_cluster  = fat_entry;                                                                                      // the relative position of the free cluster found in this sector of the FAT.
910
                {
681
                                free_cluster += (fat_sector_offset << 8);                                                       // calculate the absolute position of the free cluster in the FAT;
-
 
682
                                fat_entry = 256;                                                                                                        // terminate the search for a free cluster in this sector.
-
 
683
                        }
-
 
684
                }
-
 
685
                fat_sector_offset++;                                                                   
-
 
686
        }      
-
 
687
return(free_cluster);
-
 
688
}
-
 
689
 
-
 
690
//________________________________________________________________________________________________________________________________________
911
                        Fat16_Deinit();
691
// Funtion:     u16 AppendCluster(File *file);
-
 
692
// 
-
 
693
// Description: This function finds the next free datacluster on the disk and appends it to the specified file.
-
 
694
//                              
-
 
695
// Returnvalue: This funktion returns 1 if a cluster was appended to the specified file.
-
 
696
//________________________________________________________________________________________________________________________________________
912
                        return(0);
697
 
-
 
698
u8 AppendCluster(File *file)
-
 
699
{
913
                }
-
 
914
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
700
        u16  free_cluster = 0;                                                                                                         
915
                file->SectorOfCurrCluster = 0;
701
        u32 fat_pointer = 0;
916
                file->ByteOfCurrSector = 0;
-
 
917
        }
-
 
918
        return(new_cluster);
702
        u8 retvalue     = 0;
-
 
703
       
919
}
704
        free_cluster = FindNextFreeCluster(file);                                                                               // the next free cluster found on the disk.
-
 
705
        if(free_cluster) retvalue = 1;                                                                                                  // A free cluster was found and can be added to the end of the file. 
920
 
706
        fat_pointer  = FileAllocationTable;                                                                                             // Set Pointer to the beginnig of the FAT.
-
 
707
        fat_pointer += (u32)((u32)GetFatClusterOffset(file) >> 8);                                              // find the sector in the FAT with 256 entries per sector.
921
/****************************************************************************************************************************************************/
708
       
-
 
709
    SDC_GetSector(fat_pointer,file->buffer);                                            
922
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
-
 
923
/*                                                                                                                                                                                                                                                                                                      */
-
 
924
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
710
        Fat = (struct FatEntry *)file->buffer;
925
/*                                                                                                                                                                                                                                                                                                      */
711
        Fat[GetFatSectorIndex(file)].next_cluster = free_cluster;                                               // append the free cluster to the end of the file in the FAT.
-
 
712
        SDC_PutSector((u32)fat_pointer,file->buffer);                                                                   // save the modified sector to the FAT.
926
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
713
 
927
/****************************************************************************************************************************************************/
714
        fat_pointer  = (u32)free_cluster;
-
 
715
        fat_pointer -= 2;
-
 
716
        fat_pointer *= SectorsPerCluster;
928
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
717
        fat_pointer += FirstDataCluster;
929
{
718
 
930
        u32             dir_sector, max_dir_sector, curr_sector;
719
        file->cluster_pointer = fat_pointer;                                                                                    // continue wrtiting to the file in the new and free datacluster.
-
 
720
        return(retvalue);                                                                                                                               // return 1 when a new cluster was appended to the file
-
 
721
}
-
 
722
 
-
 
723
 
931
        u16     dir_entry = 0;
724
//________________________________________________________________________________________________________________________________________
932
 
-
 
933
        u16     end_of_directory_not_reached = 0;
-
 
934
        u8              i = 0;
-
 
935
        u8      direntry_exist = 0;
725
// Funtion:     void DeleteClusterChain(u16 startcluster);
936
        DirEntry_t * dir;
726
// 
-
 
727
// Description: This function frees all the clusters used for file from the fat.
937
 
728
//                              
938
        // if incomming pointers are useless return immediatly
729
// Returnvalue: none
939
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
730
//________________________________________________________________________________________________________________________________________
-
 
731
 
940
 
732
void DeleteClusterChain(u16 startcluster)
941
        // dir entries can be searched only in filesclusters that have 
733
{
942
        // a corresponding dir entry with adir-flag set in its attribute 
734
        u16 fat_index                   =       0;
943
        // or direct within the root directory area
735
        u16 fat_sector_offset   =       0;
944
       
736
        u32 sector_in_buffer    =       0;     
945
        file->FirstSectorOfFirstCluster = 0;
737
        u32 ul_temp                             =       0;
-
 
738
        u8 buffer[512];
946
        // no current directory exist therefore assume searching in the root
-
 
947
        if(file->DirectorySector == 0)
739
       
948
        {
740
        fat_index = (startcluster % 0x100);                                                                                             // Calculate the sector within the cluster.                                                                                                                             
949
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
-
 
950
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
-
 
951
        }
-
 
952
        // within the root directory area we can read sectors sequentially until the end of this area
-
 
953
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
-
 
954
        {
-
 
955
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
-
 
956
        }
-
 
957
        // within the data clusters we can read sectors sequentially only within the cluster  
-
 
958
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
-
 
959
        {
-
 
960
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
-
 
961
        }
-
 
962
        else return (direntry_exist); // bad sector range for directory sector of the file
741
        fat_sector_offset = (startcluster >> 8);                                                                                // and the position within the sector.
963
        // if search area is not defined yet
-
 
964
        if(file->FirstSectorOfFirstCluster == 0)
-
 
965
        {
742
        ul_temp = (u32)(FileAllocationTable + fat_sector_offset);
966
                // check if the directory entry of current file is existent and has the dir-flag set
743
               
967
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
-
 
968
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
-
 
969
                {
-
 
970
                        Fat16_Deinit();
-
 
971
                        return(direntry_exist);
744
       
-
 
745
        do
972
                }
746
        {
-
 
747
                if(sector_in_buffer != ul_temp)
-
 
748
                {
-
 
749
                        sector_in_buffer = ul_temp;
-
 
750
                        SDC_GetSector(ul_temp,buffer); 
-
 
751
                }
-
 
752
                Fat = (struct FatEntry *)buffer;
973
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
753
       
974
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
-
 
975
                {
754
                startcluster = Fat[fat_index].next_cluster;
976
                        case SLOT_EMPTY:
755
                Fat[fat_index].next_cluster = 0x0000;                                                                           // free the cluster within the fat.
977
                        case SLOT_DELETED:
756
 
978
                                // the directrory pointer of this file points to a deleted or not existen directory
757
                fat_index = (startcluster % 0x100);                                                                                     // Calculate the sector within the cluster.                                                                                                                             
979
                                // therefore no file or subdirectory can be created
758
                fat_sector_offset = (startcluster >> 8);                                                                        // and the position within the sector.
980
                                return (direntry_exist);
-
 
981
                                break;
759
                ul_temp = (u32)(FileAllocationTable + fat_sector_offset);
982
                        default:        // and is a real directory 
760
                if((sector_in_buffer != ul_temp) || (startcluster == 0xffff))
983
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
761
                {
-
 
762
                        SDC_PutSector(sector_in_buffer,buffer);
984
                                {       // current file is not a directory therefore no file or subdirectory can be created here
763
                }
985
                                        return (direntry_exist);
764
        }
-
 
765
        while(startcluster != 0xffff);                                                                                                  // last cluster has been deleted.
986
                                }
766
}
-
 
767
 
-
 
768
 
-
 
769
//________________________________________________________________________________________________________________________________________
987
                                break;
-
 
988
                }
770
// Funtion:     u16 GetFatClusterIndex(File *file);
989
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
-
 
990
        }
-
 
991
 
-
 
992
        // update current file data area position to start of first cluster
-
 
993
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
-
 
994
        file->SectorOfCurrCluster               = 0;           
-
 
995
        file->ByteOfCurrSector                  = 0;
-
 
996
 
-
 
997
        do // loop over all data clusters of the current directory entry
-
 
998
        {      
-
 
999
                dir_sector = 0; // reset sector counter within a new cluster
-
 
1000
                do // loop over all sectors of a cluster or all sectors of the root directory
-
 
1001
                {      
-
 
1002
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
-
 
1003
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
-
 
1004
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
-
 
1005
                        {
771
// 
1006
                                Fat16_Deinit();
-
 
1007
                                return(direntry_exist);
-
 
1008
                        }
-
 
1009
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
-
 
1010
                        // search all directory entries within that sector
-
 
1011
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
-
 
1012
                        {   // check for existing dir entry
-
 
1013
                                switch((u8)dir[dir_entry].Name[0])
-
 
1014
                                {
-
 
1015
                                        case SLOT_EMPTY:
-
 
1016
                                        case SLOT_DELETED:
772
// Description: This function returns the clusterindex of the cluster specified by file->cluster_pointer of the specified file.
1017
                                                // ignore empty or deleted dir entries
-
 
1018
                                                break;
773
//                              
1019
                                        default:
-
 
1020
                                                // if existing check attributes before names are compared will safe performance
774
//________________________________________________________________________________________________________________________________________
1021
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
775
 
1022
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
-
 
1023
                                                i = 0;
776
u16 GetFatClusterOffset(File *file)
1024
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
777
{
1025
                                                if (i < 10) break; // names does not match
778
        u32 fat_sector_offset   =       0;
-
 
779
 
-
 
780
        fat_sector_offset   = ((file->cluster_pointer) - (FirstDataCluster));                   // Calculate index of actual cluster in FAT.
-
 
781
        fat_sector_offset  /= SectorsPerCluster;                                                                                                               
-
 
782
        fat_sector_offset  += 2;                                                                                                                // In Fat16 clusterpositions have an offset of two.                                                             
-
 
783
       
-
 
784
        return((u16)fat_sector_offset);
-
 
785
}
-
 
786
 
-
 
787
//________________________________________________________________________________________________________________________________________
-
 
788
// Funtion:     u16 GetFatSectorIndex(File *file);
-
 
789
// 
-
 
-
 
1026
                                                // if dirname and attribute have matched
-
 
1027
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
-
 
1028
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster                                                        
-
 
1029
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
-
 
1030
                                                file->SectorOfCurrCluster = 0;
-
 
1031
                                                file->ByteOfCurrSector = 0;
-
 
1032
                                                file->DirectorySector = curr_sector; // current sector
-
 
1033
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
790
// Description: This function returns the sectorindex of the cluster specified by file->cluster_pointer of the specified file.
1034
                                                file->Size = dir[dir_entry].Size;      
791
//                              
1035
                                                direntry_exist = 1; // mark as found    
792
//________________________________________________________________________________________________________________________________________
1036
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop        
-
 
1037
                                } // end of first byte of name check
-
 
1038
                        }
793
 
1039
                        dir_sector++; // search next sector
794
u16 GetFatSectorIndex(File *file)
1040
                // stop if we reached the end of the cluster or the end of the root dir
795
{
-
 
796
        u16 fat_pointer                 =       0;
1041
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
797
       
-
 
798
        fat_pointer = GetFatClusterOffset(file);
1042
 
799
        fat_pointer = fat_pointer % 0x100;                                                                                              // Calculate the clusterposition in the fat                                                                                                                             
-
 
800
       
1043
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
-
 
1044
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))                                                                                  
801
        return(fat_pointer);
1045
                {
-
 
1046
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
-
 
1047
                }
802
}
1048
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
-
 
1049
        return(direntry_exist);
803
 
1050
}
804
//________________________________________________________________________________________________________________________________________
-
 
805
// Funtion:     u16 CreateFileInDirectory(u8 *, File *)
-
 
806
// 
-
 
807
// Description: This function looks for the next free position in the directory and creates an entry. The type of an directoryentry is
-
 
808
//                              specified by the attribute. 
-
 
809
//                              bit0:   unused
-
 
810
//                              bit1:   archive
-
 
811
//                              bit2:   read_only
-
 
812
//                              bit3:   system  
1051
 
813
//                              bit4:   directory
1052
 
814
//                              bit5:   volume
-
 
815
//________________________________________________________________________________________________________________________________________
-
 
816
 
-
 
817
u8 CreateFileInDirectory(s8 *fname, File *file)
-
 
818
{
-
 
819
        u16     rootentry       = 0;                                                                                                            // index to an entry in the rootdirectory.
-
 
820
        u16     cnt_enries_searched = 0;                                                                                                // count the number of rootentries which have been searched already.
-
 
821
        u8              i = 0;
-
 
822
        u16     sector_offset = 0;                                                                                                              // index to the sector of the Rootentry which is searched momentarily
-
 
823
        u8              retvalue = 0;
-
 
824
        u32             cluster_temp = 0;
1053
/****************************************************************************************************************************************/
825
        u16             cluster = 0;
-
 
826
        s8 name[11]     = "           ";                       
-
 
827
 
-
 
828
        SeperateFileName(fname,name);
1054
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
-
 
1055
/*                                                                                                                                                                                                                                                                              */
-
 
1056
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
829
 
1057
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
830
        cluster_temp = (u32)FindNextFreeCluster(file);                                                                  // the next free cluster on the disk.
1058
/*                                                                                                                                                                                                                                                                              */
831
       
1059
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
832
        if(cluster_temp)                                                                                                                                // if a free cluster is available:
1060
/****************************************************************************************************************************************/
-
 
1061
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
833
        {
1062
{
834
                cluster = (u16)cluster_temp;                                                                                            // remember the index of the free datacluster found for the directory entry.
-
 
835
                cluster_temp -=2;                                                                                                                       // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
1063
        u32 dir_sector, max_dir_sector, curr_sector;
836
                cluster_temp *= SectorsPerCluster;                                                                                      // Calculate relative sectorindex of first datacluster.
1064
        u16 dir_entry   = 0;
-
 
1065
        u16 subdircluster, dircluster = 0;
-
 
1066
        u16 end_of_directory_not_reached = 0;
-
 
1067
        u8      i                       = 0;
-
 
1068
        u8      retvalue        = 0;   
-
 
1069
        DirEntry_t *dir;
-
 
1070
 
-
 
1071
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
-
 
1072
        // It is not checked here that the dir entry that should be created is already existent!
-
 
1073
       
-
 
1074
        // Dir entries can be created only in file-clusters that have 
837
                file->start_cluster   = (FirstDataCluster + cluster_temp);                                      // Calculate absolute sectorposition of first datacluster.
1075
        // the dir-flag set in its attribute or within the root directory
838
                file->cluster_pointer = file->start_cluster;                                                            // start reading the file with the first sector of the first datacluster.
1076
       
-
 
1077
        file->FirstSectorOfFirstCluster = 0;
839
       
1078
        // no current directory exist therefore assume creating in the root
-
 
1079
        if(file->DirectorySector == 0)
-
 
1080
        {
-
 
1081
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
-
 
1082
                dircluster = 0;
-
 
1083
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
-
 
1084
        }
-
 
1085
        // within the root directory area we can read sectors sequentially until the end of this area
-
 
1086
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
840
                                                                                                                                                                        // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
1087
        {
-
 
1088
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
-
 
1089
        }
-
 
1090
        // within the data clusters we can read sectors sequentially only within the cluster  
841
                do
1091
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
842
                {                                                                                                                                                       // search the next 16 rootentries in this sector of the roordirectory.
1092
        {
843
                        rootentry=0;                                                                   
-
 
844
                        SDC_GetSector((u32)(CWD + sector_offset),file->buffer);                         // Read the Rootdirectory.
-
 
845
                        DirectoryEntry = (struct DirEntry *)file->buffer;
-
 
846
                        while((rootentry<16) && (!retvalue))
1093
                max_dir_sector = Partition.SectorsPerCluster;
847
                        {
-
 
848
                                if((DirectoryEntry[rootentry].attribute == 0) || (DirectoryEntry[rootentry].attribute == 0xE5)) // empty directory entry found
-
 
849
                                {
-
 
850
                                        for(i=0;i<11;i++) DirectoryEntry[rootentry].name[i] = name[i];// Kopie the filename and the file extension to the directoryentry.
-
 
851
                                        DirectoryEntry[rootentry].attribute    = _FILE;                                 // Set the fileattribute to archive to reserve the directoryentry.
1094
        }
852
                                        DirectoryEntry[rootentry].startcluster = cluster;                               // copy the location of the first datacluster to the directoryentry.
1095
        else return (retvalue); // bad sector range for directory sector of the file 
853
                                        DirectoryEntry[rootentry].size     = 0;                                                 // the new createted file has no content yet.
-
 
854
                                        file->directory_sector = (u32) (CWD + sector_offset);
1096
        // if search area is not defined yet
855
                                        file->directory_index  = (u8) rootentry;
-
 
856
                                        retvalue = 1;
-
 
857
                                        SDC_PutSector((u32)(CWD + sector_offset),file->buffer);                        
1097
        if(file->FirstSectorOfFirstCluster == 0)
858
                                }                      
-
 
859
                                rootentry++;
-
 
860
                                cnt_enries_searched++;
-
 
861
                        }
-
 
862
                        if(!retvalue)                                                                                                                   // file not found in this sector so take next sector.
-
 
863
                        {
-
 
864
                                rootentry = 0;
-
 
865
                                sector_offset++;
-
 
866
                        }
-
 
867
                }
-
 
868
                while((cnt_enries_searched< PossibleRootEntries) && (!retvalue));
-
 
869
 
1098
        {
870
        }
-
 
871
        return(retvalue);                                                                                                                               // return 1 if file has been created otherwise return 0.
-
 
872
}
1099
            // check if the directory entry of current file is existent and has the dir-flag set
873
 
1100
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
874
//________________________________________________________________________________________________________________________________________
1101
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
875
// Funtion:     u16 SeekFileInDirectory(s8 *fname, File *)
1102
                {
-
 
1103
                        Fat16_Deinit();
876
// 
1104
                        return(retvalue);
-
 
1105
                }              
877
// Description: this function searches all possible entries withint the actual directory for the specified object.
1106
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
878
//                              
1107
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
879
// Returnvalue: This function returns 1 if the directoryentry specified was found.
1108
                {
880
//________________________________________________________________________________________________________________________________________
1109
                        case SLOT_EMPTY:
-
 
1110
                        case SLOT_DELETED:
-
 
1111
                                return (retvalue);
-
 
1112
                                break;
-
 
1113
                        default:        // and is a real directory 
-
 
1114
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
-
 
1115
                                {       // current file is not a directory therefore no file or subdirectory can be created here
881
 
-
 
-
 
1116
                                        return (retvalue);
-
 
1117
                                }
882
u8 SeekFileInDirectory(s8 *fname, File *file)
1118
                                break;
-
 
1119
                }
-
 
1120
                dircluster = dir[file->DirectoryIndex].StartCluster;
-
 
1121
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
883
{
1122
        }
884
        u16     rootentry=0;
-
 
885
        u16     end_of_directory_not_reached = 0;                                                                               // the directory has been read completely without a result.
-
 
886
        u8              i=0;
-
 
887
        u8      retvalue = 0;
-
 
888
        u32     cluster_temp = 0;
-
 
889
        s8 name[11]     = "           ";                       
-
 
890
       
-
 
891
        SeperateFileName(fname,name);
1123
               
892
       
1124
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
893
        file->cluster_pointer = CWD;                                                                                                    // start looking for the file in the actual directory.
1125
        if(subdircluster)
-
 
1126
        {
-
 
1127
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
-
 
1128
                file->SectorOfCurrCluster               = 0;
-
 
1129
                do // loop over all clusters of current directory
-
 
1130
                {      
-
 
1131
                        dir_sector = 0; // reset sector counter within a new cluster
-
 
1132
                        do // loop over all sectors of a cluster or all sectors of the root directory
-
 
1133
                        {
-
 
1134
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number                                                                      
-
 
1135
                                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
-
 
1136
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
-
 
1137
                                {
-
 
1138
                                        Fat16_Deinit();
-
 
1139
                                        return(retvalue);
-
 
1140
                                }              
894
 
1141
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
895
                                                                                                                                                                        // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
1142
                                // search all directory entries of a sector
-
 
1143
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
-
 
1144
                                {       // check if current direntry is available
-
 
1145
                                        if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
-
 
1146
                                        {       // a free direntry was found    
-
 
1147
                                                for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
-
 
1148
                                                dir[dir_entry].Attribute    = attrib;                                                           // Set the attribute of the new directoryentry.
-
 
1149
                                                dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
-
 
1150
                                                dir[dir_entry].DateTime         = FileDateTime(&SystemTime);                    // set date/time
-
 
1151
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
-
 
1152
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
-
 
1153
                                                {
-
 
1154
                                                        Fat16_Deinit();
-
 
1155
                                                        return(retvalue);
-
 
1156
                                                }
-
 
1157
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
-
 
1158
                                                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
896
        do
1159
                                                file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
897
        {                                                                                                                                                               // search the next 16 rootentries in this sector of the roordirectory.
1160
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
-
 
1161
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
898
                rootentry=0;                                                                   
1162
                                                file->Size                                              = 0;                                                        // new file has no size
899
                SDC_GetSector((u32) file->cluster_pointer,file->buffer);                                        // Read the Rootdirectory.
1163
                                                file->DirectorySector                   = curr_sector;
900
                DirectoryEntry = (struct DirEntry *)file->buffer;
1164
                                                file->DirectoryIndex                    = dir_entry;
901
 
-
 
902
                while((!retvalue)&&(rootentry<16))
1165
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area          
-
 
1166
                                                {      
903
                {
1167
                                                        ClearCurrCluster(file); // fill cluster with zeros
904
                        i=0;
-
 
905
                        if(DirectoryEntry[rootentry].name[0] != 0xe5)                                                   // ignore deleted items.
-
 
906
                        {
-
 
907
                                while((i<=10)&&(DirectoryEntry[rootentry].name[i] == name[i]))
-
 
908
                                {
-
 
909
                                        i++;
-
 
910
                                }
-
 
911
                        }
-
 
912
 
-
 
913
                        if((i==11) && (DirectoryEntry[rootentry].attribute & _FILE))                    // entry found!! -> reading startcluster of entry from offset 26.
-
 
914
                        {
-
 
915
                                cluster_temp = (u32)DirectoryEntry[rootentry].startcluster;                                                    
-
 
916
                                cluster_temp -=2;                                                                                                       // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
-
 
917
                                cluster_temp *= (u32)SectorsPerCluster;                                                         // Calculate positon of first cluster.
-
 
918
                                file->start_cluster   = (FirstDataCluster + cluster_temp);
-
 
919
                                file->directory_sector = (u32) file->cluster_pointer;
-
 
920
                                file->cluster_pointer = file->start_cluster;                                            // start reading the file with the first cluster.
-
 
921
                                file->filesize = (u32) DirectoryEntry[rootentry].size;
-
 
922
                                file->directory_index  = (u8) rootentry;
-
 
923
                                retvalue = 1;
-
 
924
                        }
-
 
925
                        rootentry++;
-
 
926
                }
-
 
927
                if(!retvalue)                                                                                                                           // file not found in this sector so take next sector.
-
 
928
                {
-
 
929
                        end_of_directory_not_reached = GetNextCluster(file);
-
 
930
                }
-
 
931
        }
1168
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
932
        while((end_of_directory_not_reached) && (!retvalue));
1169
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
933
        return(retvalue);
-
 
-
 
1170
                                                        {
934
}
1171
                                                                Fat16_Deinit();
935
 
1172
                                                                return(retvalue);
-
 
1173
                                                        }      
936
 
1174
                                                        dir = (DirEntry_t *)file->Cache;
937
 
1175
                                                        // create direntry "." to current dir
938
//________________________________________________________________________________________________________________________________________
1176
                                                        dir[0].Name[0] = 0x2E;
939
// Funtion:     void SeperateFileName(u8*);
1177
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
-
 
1178
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
-
 
1179
                                                        dir[0].StartCluster = subdircluster;
-
 
1180
                                                        dir[0].DateTime = 0;
-
 
1181
                                                        dir[0].Size = 0;
-
 
1182
                                                        // create direntry ".." to the upper dir
940
// 
1183
                                                        dir[1].Name[0] = 0x2E;
941
// Description: This function seperates the filename and the fileattribute and brings them into the needed format ('test.txt' -> 'TEST    TXT');
-
 
942
//                              
1184
                                                        dir[1].Name[1] = 0x2E;
943
//________________________________________________________________________________________________________________________________________
1185
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
-
 
1186
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
-
 
1187
                                                        dir[1].StartCluster = dircluster;
-
 
1188
                                                        dir[1].DateTime = 0;
-
 
1189
                                                        dir[1].Size = 0;
-
 
1190
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. 
-
 
1191
                                                        {
-
 
1192
                                                                Fat16_Deinit();
-
 
1193
                                                                return(retvalue);
-
 
1194
                                                        }              
-
 
1195
                                                }      
-
 
1196
                                                retvalue = 1;
-
 
1197
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop        
-
 
1198
                                        }
-
 
1199
                                }                      
-
 
1200
                                dir_sector++; // search next sector
-
 
1201
                        // stop if we reached the end of the cluster or the end of the root dir
-
 
1202
                        }while((dir_sector < max_dir_sector) && (!retvalue));
-
 
1203
                       
-
 
1204
                        // if we are seaching in the data area and the file not found in this cluster so take next cluster.
-
 
1205
                        if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))                                                                                
-
 
1206
                        {
-
 
1207
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
-
 
1208
                        }
-
 
1209
                }while((end_of_directory_not_reached) && (!retvalue));
-
 
1210
                // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
-
 
1211
                // Then we would need to add a cluster to that file and create the new direntry there.
-
 
1212
                // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
-
 
1213
                // within a subdirectory of root.
-
 
1214
        }
-
 
1215
        return(retvalue);       // return 1 if file has been created otherwise return 0.
-
 
1216
}
-
 
1217
 
-
 
1218
/********************************************************************************************************************************************/
-
 
1219
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
944
 
1220
/*                                                                                                                                                                                                                                                                                      */
945
void SeperateFileName(s8 *fname, s8 *name)
1221
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
946
{
1222
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
947
        u8 readpointer  = 0;
-
 
948
        u8 writepointer = 0;
-
 
949
        u8 attribute    = 1;
1223
/*                                      updated.                                                                                                                                                                                                                                */
950
        u8 i = 0;
1224
/*                                                                                                                                                                                                                                                                                      */
951
       
1225
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
952
       
1226
/********************************************************************************************************************************************/
953
        while((writepointer<=10) && (fname[readpointer]!=0))                                                    // the rootdirectoryentry is 8bytes for filename and 3bytes for fileattribute.
1227
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
954
        {                                                                                                                                                               // the filename in the rootdirectory is in the format "TEST    TXT" without the dot.
1228
{
955
                if(fname[readpointer]=='.')                                                                                             // seperating filename and attribute.
-
 
956
                {
-
 
957
                        if(attribute)                                                                                                                   // is the filename "." or ".." ?
1229
        s8* path = 0;
958
                        {
1230
        s8* subpath = 0;
959
                                name[writepointer] = fname[readpointer];
1231
        u8 af, am, file_exist = 0;
960
                                readpointer++;
1232
        s8 dirname[12]; // 8+3 + temination character
961
                                writepointer++;                
1233
 
962
                        }
1234
        // if incomming pointers are useless return immediatly
963
                        else
1235
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
964
                        {
1236
 
965
                                if(fname[(readpointer-1)] != '*')
1237
        // trace along the filepath
966
                                {
1238
        path = (s8*)filename;                                                           // start a the beginning of the filename string
967
                                        for(i=writepointer;i<8;i++)
1239
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
968
                                        {
1240
        file->DirectoryIndex = 0;
969
                                                name[i] = ' ';
1241
        // as long as the file was not found and the remaining path is not empty
970
                                        }
1242
        while((*path != 0) && !file_exist)
971
                                }
1243
        {       // separate dirname and subpath from filepath string
972
                                readpointer++;
1244
                subpath = SeperateDirName(path, dirname);
973
                                writepointer = 8;
1245
                if(subpath != NULL)
974
                        }
1246
                {      
975
                }
1247
                        if(*subpath == 0)        
976
                else if(fname[readpointer] == '*')                                                                                      // wildcard found within the filename + extension.
1248
                        {       // empty subpath indicates last element of dir chain
977
                {
1249
                                af = attribfilter;
978
                        if(writepointer < 8)                                                                                                    // in extension.
1250
                                am = attribmask;
979
                        {
1251
                        }
980
                                readpointer++;
1252
                        else  // it must be a subdirectory and no volume label
981
                                writepointer = 8;                                      
1253
                        {
982
                        }
1254
                                af = ATTR_SUBDIRECTORY;
983
                        else                                                                                                                                    // in filename.
1255
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
984
                        {
1256
                        }
985
                                writepointer = 11;                                                                                                      // jump to the end of the string to terminate this function.
1257
                        if(!DirectoryEntryExist(dirname, af, am, file))
986
                        }
1258
                        {
987
                        attribute = 0;
1259
                                return (file_exist); // subdirectory does not exist
988
                }
1260
                        }
989
                else
1261
                        else
990
                {
1262
                        {      
991
                        if((fname[readpointer]>96) && (fname[readpointer]<123))
1263
                                if (*subpath == 0)
992
                        {
1264
                                {
993
                                name[writepointer]=(fname[readpointer] - 32);                                           // all characters must be upper case.
1265
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
994
                        }
1266
                                }
995
                        else
-
 
996
                        {
-
 
997
                                name[writepointer]=fname[readpointer];
-
 
998
                        }      
1267
                        }
999
                        readpointer++;
-
 
1000
                        writepointer++;
-
 
1001
                        attribute = 0;
-
 
1002
                }
1268
                }
-
 
1269
                else // error seperating the subpath
-
 
1270
                {
-
 
1271
                        return file_exist; // bad subdir format
-
 
1272
                }
-
 
1273
                path = subpath;
-
 
1274
                subpath = 0;
1003
        }      
1275
        }
-
 
1276
        return (file_exist);
1004
}
1277
}
1005
 
-
 
1006
//________________________________________________________________________________________________________________________________________
-
 
1007
// Funtion:     File * ReserveFilePointer_(void);
-
 
1008
// 
-
 
1009
// Description: This function looks for a free filepointer and reserves it.
-
 
1010
//                              
-
 
1011
//
-
 
1012
//      Return:         NULL = faild to reserve a filepointer
-
 
1013
//                              otherwise filepointer
-
 
-
 
1278
 
-
 
1279
 
-
 
1280
/********************************************************************************************************************************************/
-
 
1281
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
-
 
1282
/*                                                                                                                                                                                                                                                                                      */
-
 
1283
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
-
 
1284
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
-
 
1285
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */                                                                                                             
-
 
1286
/*                                                                                                                                                                                                                                                                                      */
1014
//________________________________________________________________________________________________________________________________________
1287
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1015
 
1288
/********************************************************************************************************************************************/
1016
File * ReserveFilePointer(void)
1289
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1017
{
1290
{
-
 
1291
        s8 *path = 0;
1018
        File *file;
1292
        s8 *subpath = 0;
-
 
1293
        u8 af, am, file_created = 0;
-
 
1294
        s8 dirname[12];
-
 
1295
 
-
 
1296
        // if incomming pointers are useless return immediatly
-
 
1297
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
-
 
1298
 
-
 
1299
        // trace along the filepath
-
 
1300
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
-
 
1301
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
-
 
1302
        file->DirectoryIndex = 0;
1019
        file = NULL;
1303
        // as long as the file was not created and the remaining file path is not empty
-
 
1304
        while((*path != 0) && !file_created)
1020
        u8      temp;
1305
        {   // separate dirname and subpath from filepath string
-
 
1306
                subpath = SeperateDirName(path, dirname);
-
 
1307
                if(subpath != NULL)
-
 
1308
                {
1021
       
1309
                        if(*subpath == 0)        
-
 
1310
                        {       // empty subpath indicates last element of dir chain
-
 
1311
                                af = ATTR_NONE;
1022
        for(temp = 0;temp<__MAX_FILES_USED;temp++)
1312
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1023
        {
1313
                        }
1024
                if(FilePointer[temp].state == _UNUSED)                                                                          // free filepointer found?
1314
                        else  // it must be a subdirectory and no volume label
1025
                {
-
 
1026
                        file = &FilePointer[temp];
-
 
1027
                        FilePointer[temp].state                                 = _USED;                                                // mark as used.
-
 
1028
                        FilePointer[temp].mode                                  = 0;                                                    // type of access (read/write) not defined yet.
-
 
1029
                        FilePointer[temp].start_cluster                 = 0;                                                    // Sectorpointer to the first sector of the first datacluster of the file. 
-
 
1030
                        FilePointer[temp].cluster_pointer               = 0;                                                    // Pointer to the cluster which is edited at the moment.
-
 
1031
                        FilePointer[temp].sector_index                  = 0;                                                    // The sector which is edited at the moment (cluster_pointer + sector_index).
-
 
1032
                        FilePointer[temp].byte_index                    = 0;                                                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
-
 
1033
                        FilePointer[temp].filesize                              = 0;                                                    // the size of the opend file in bytes.
-
 
1034
                        FilePointer[temp].fileposition                  = 0;                                                    // pointer to a character within the file 0 < fileposition < filesize
-
 
1035
                        FilePointer[temp].sector_in_buffer              = 0;                                                    // the last sector read, wich is still in the sectorbuffer.
-
 
1036
                        FilePointer[temp].directory_sector              = 0;                                                    // the sectorposition where the directoryentry has been made.
-
 
1037
                        FilePointer[temp].directory_index               = 0;                                                    // the index to the directoryentry within the specified sector.
1315
                        {
-
 
1316
                                af = ATTR_SUBDIRECTORY;
-
 
1317
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
-
 
1318
                        }
-
 
1319
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
-
 
1320
                        {  // try to create subdir or file
-
 
1321
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1038
                        FilePointer[temp].attribute                     = 0;                                                    // the attribute of the file opened.
1322
                                if(!CreateDirectoryEntry(dirname, af, file))
1039
                        break;
1323
                                {       // could not be created
1040
                }
1324
                                        return(file_created);  
1041
        }
-
 
1042
        return(file);
-
 
1043
}
-
 
1044
 
-
 
1045
 
-
 
1046
//________________________________________________________________________________________________________________________________________
-
 
1047
// Funtion:     void FreeFilePointer_(File *);
-
 
1048
// 
-
 
1049
// Description: This function free's the filepointer by marking it as unused.
-
 
1050
//                              
-
 
1051
//
-
 
1052
//      Return:         none
-
 
1053
//                              
-
 
1054
//________________________________________________________________________________________________________________________________________
-
 
1055
 
-
 
1056
void FreeFilePointer(File *file)
-
 
1057
{
-
 
1058
        u8 cnt = 0;
1325
                                }
1059
       
1326
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1060
        for(cnt=0;cnt<__MAX_FILES_USED;cnt++)                                                                                   // Is the filepointeradress vaild?
1327
                        }
1061
        {
1328
                }
1062
                if(&FilePointer[cnt] == file)                                                                                           // filepointer found therefore it must be valid
1329
                else // error seperating the subpath
-
 
1330
                {
-
 
1331
                        return file_created; // bad subdir format
1063
                {
1332
                }
-
 
1333
                path = subpath;
1064
                        FilePointer[cnt].state = _UNUSED;                                                                               // and can be marked as unused.
1334
                subpath = 0;
1065
                }
1335
        }
1066
        }
1336
        return (file_created);
1067
}
1337
}
1068
 
1338
 
1069
 
1339
 
-
 
1340
/********************************************************************************************************************************************/
1070
//________________________________________________________________________________________________________________________________________
1341
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1071
// Funtion:     void DelteDirectoryEntry(Find *)
-
 
1072
// 
1342
/*                                                                                                                                                                                                                                                                                      */
1073
// Description: This function deletes the directoryentry of the specified item.
-
 
1074
//                              
-
 
-
 
1343
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
-
 
1344
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1075
//                              
1345
/*                                                                                                                                                                                                                                                                                      */
1076
// returnvalue: 1 if the directory could be created.
1346
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1077
//________________________________________________________________________________________________________________________________________
-
 
1078
 
1347
/********************************************************************************************************************************************/
1079
void DeleteDirectoryEntry(Find *item)
1348
File_t * fopen_(const s8 *filename, const s8 mode)
1080
{
1349
{                      
1081
        u8 buffer[512];
-
 
1082
       
-
 
1083
       
-
 
1084
        SDC_GetSector((u32) item->cluster_pointer,buffer);                                                              // Read the Rootdirectory.
-
 
1085
        DirectoryEntry = (struct DirEntry *)buffer;
-
 
1086
 
-
 
1087
        DirectoryEntry[(item->directory_index)-1].attribute = 0;                                                // free the directoryentry.
-
 
1088
        DirectoryEntry[(item->directory_index)-1].name[0] = 0xE5;                                               // free the directoryentry.
-
 
1089
        SDC_PutSector((u32) item->cluster_pointer,buffer);                                                              // Read the Rootdirectory.
-
 
-
 
1350
        File_t *file    = 0;
-
 
1351
       
-
 
1352
        if((!Partition.IsValid) || (filename == 0)) return(file);
-
 
1353
 
-
 
1354
        // Look for an unused filepointer in the file pointer list?
-
 
1355
        file = LockFilePointer();
-
 
1356
        // if no unused file pointer was found return 0
-
 
1357
        if(file == NULL) return(file);
-
 
1358
 
-
 
1359
        // now we have found a free filepointer and claimed it
-
 
1360
        // so let initiate its property values
-
 
1361
        file->FirstSectorOfFirstCluster = 0;            // Sectorpointer to the first sector of the first datacluster of the file. 
-
 
1362
        file->FirstSectorOfCurrCluster  = 0;            // Pointer to the cluster which is edited at the moment.
-
 
1363
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
-
 
1364
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
-
 
1365
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
-
 
1366
        file->Size                                              = 0;            // the size of the opened file in bytes.
-
 
1367
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1090
}
-
 
1091
 
1368
        file->SectorInCache                             = 0;            // the last sector read, wich is still in the sectorbuffer.
1092
 
-
 
1093
 
1369
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1094
 
-
 
1095
//________________________________________________________________________________________________________________________________________
-
 
1096
// Funtion:     u8 CreateSubDirectory(u8 *)
1370
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1097
// 
-
 
1098
// Description: This function creates an directory within the directory specified by CWD
-
 
1099
//                              
1371
        file->Attribute                                 = 0;            // the attribute of the file opened.
1100
//                              
1372
 
1101
// returnvalue: 1 if the directory could be created.
1373
        // check if a real file (no directory) to the given filename exist
1102
//________________________________________________________________________________________________________________________________________
1374
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1103
 
-
 
1104
u8 CreateSubDirectory(s8 *fname)
1375
        {  // file exist
1105
{
-
 
1106
        u16     index   = 0;                                                                                                                    // index to an entry in the rootdirectory.
-
 
1107
        u16     cnt_entries_searched = 0;                                                                                               // count the number of rootentries which have been searched already.
1376
                switch(mode)  // check mode
1108
        u16             i = 0;
1377
                {
1109
        u16     sector_offset = 0;                                                                                                              // index to the sector of the entry which is searched momentarily
-
 
1110
        u8              retvalue = 0;
-
 
1111
        u32             cluster_temp = 0;
-
 
1112
        u16             cluster = 0;
-
 
1113
        File    file;
-
 
1114
        s8              name[11] = {"           "};
-
 
1115
 
-
 
1116
        SeperateFileName(fname,name);
-
 
1117
        cluster_temp = (u32)FindNextFreeCluster(&file);                                                         // the next free cluster on the disk.
-
 
1118
       
-
 
1119
        if(cluster_temp)                                                                                                                                // if a free cluster is available:
-
 
1120
        {
-
 
1121
                cluster = (u16)cluster_temp;                                                                                            // remember the index of the free datacluster found for the directory entry.
-
 
1122
                cluster_temp -=2;                                                                                                                       // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
-
 
1123
                cluster_temp *= SectorsPerCluster;                                                                                      // Calculate relative sectorindex of first datacluster.
-
 
1124
                file.start_cluster   = (FirstDataCluster + cluster_temp);                                       // Calculate absolute sectorposition of first datacluster.
-
 
1125
                file.cluster_pointer = file.start_cluster;                                                                      // start reading the file with the first sector of the first datacluster.
-
 
1126
       
1378
                        case 'a':       // if mode is: append to file
1127
// -Initialise new cluster to zero--------------------------------------------------------
-
 
1128
                for(i=0;i<512;i++)
1379
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
-
 
1380
                                {       // file is marked as readonly --> do not open this file
1129
                {
1381
                                        fclose_(file);
1130
                        file.buffer[i] = 0;                                                                                                             // initialise buffer to zero
1382
                                        file = NULL;
1131
                }
-
 
1132
                for(sector_offset=0;sector_offset<SectorsPerCluster;sector_offset++)            // initialise all sectors of new cluster with buffer.
-
 
1133
                {
1383
                                }
1134
                        SDC_PutSector((u32)(file.start_cluster + sector_offset),file.buffer);   // save the initialised sector to the card.     
1384
                                else
1135
                }
1385
                                {       // file is not marked as read only --> goto end of file
1136
// -Create directoryentry "." -------------------------------------------------------------
-
 
1137
                DirectoryEntry = (struct DirEntry *)file.buffer;
1386
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1138
                DirectoryEntry[0].name[0] = '.';                                                                       
1387
                                }
1139
                DirectoryEntry[0].attribute = _DIRECTORY;                                                      
-
 
1140
                DirectoryEntry[0].startcluster = cluster;                                                                      
1388
                                break;
1141
// -Create directoryentry "." -------------------------------------------------------------
-
 
1142
                DirectoryEntry[1].name[0] = '.';                                                                       
-
 
1143
                DirectoryEntry[1].name[1] = '.';                                                                       
1389
                        case 'w':       // if mode is: write to file
1144
                DirectoryEntry[1].attribute = _DIRECTORY;                                                      
1390
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1145
                if(CWD == RootDirectory)
-
 
1146
                {
1391
                                {       // file is marked as readonly --> do not open this file
1147
                        DirectoryEntry[1].startcluster = 0;                                                                                    
1392
                                        fclose_(file);
1148
                }
-
 
1149
                else
1393
                                        file = NULL;
1150
                {
-
 
1151
                        cluster_temp = (CWD - FirstDataCluster);
-
 
1152
                        cluster_temp /= SectorsPerCluster;
-
 
1153
                        cluster_temp -= 2;
-
 
1154
                        DirectoryEntry[1].startcluster = (u16) cluster_temp;                                                                                                   
-
 
1155
                }
-
 
1156
                SDC_PutSector((u32) file.start_cluster,file.buffer);                                            // save the initialised sector to the card.     
1394
                                }
1157
// -create directoryentry within the cwd --------------------------------------------------
-
 
1158
                sector_offset = 0;
1395
                                else
1159
                cnt_entries_searched = 0;
1396
                                {       // file is not marked as read only --> goto start of file
1160
                do
1397
                                        // free all clusters of that file
1161
                {                                                                                                                                                       // search the next 16 rootentries in this sector of the roordirectory.
-
 
1162
                        index=0;                                                                       
-
 
1163
                        SDC_GetSector((u32)(CWD + sector_offset),file.buffer);                                  // Read the actual directory.
-
 
1164
                        DirectoryEntry = (struct DirEntry *)file.buffer;
-
 
1165
                        while((index<16) && (!retvalue))
-
 
1166
                        {
-
 
1167
                                if((DirectoryEntry[index].attribute == 0) || (DirectoryEntry[index].attribute == 0xE5)) // empty directory entry found
-
 
1168
                                {
1398
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1169
                                        for(i=0;i<11;i++) DirectoryEntry[index].name[i] = name[i];      // Kopie the filename and the file extension to the directoryentry.
1399
                                        // mar an empy cluster as the last one and store the corresponding sector
1170
                                        DirectoryEntry[index].attribute    = _DIRECTORY;                                // Set the fileattribute to archive to reserve the directoryentry.
1400
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file));
1171
                                        DirectoryEntry[index].startcluster = cluster;                                   // copy the location of the first datacluster to the directoryentry.
1401
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1172
                                        DirectoryEntry[index].size     = 0;                                                             // the new createted file has no content yet.
1402
                                        file->SectorOfCurrCluster = 0;
1173
                                        file.directory_sector = (u32) (CWD + sector_offset);
1403
                                        file->ByteOfCurrSector = 0;
-
 
1404
                                        file->Size = 0;
-
 
1405
                                        file->Position = 0;
1174
                                        file.directory_index  = (u8) index;
1406
                                        fseek_(file, 0, SEEK_SET);
-
 
1407
                                }
-
 
1408
                                break;
-
 
1409
                        case 'r':       // if mode is: read from file
-
 
1410
                                // goto end of file 
-
 
1411
                                fseek_(file, 0, SEEK_SET);
1175
                                        retvalue = 1;
1412
                                break;
-
 
1413
                        default: // other modes are not supported
-
 
1414
                                fclose_(file);
1176
                                        SDC_PutSector((u32)(CWD + sector_offset),file.buffer);                         
1415
                                file = NULL;
-
 
1416
                        break;
-
 
1417
                }
1177
                                }                      
1418
                return(file);  
1178
                                index++;
1419
        }
-
 
1420
        else // file does not exist
-
 
1421
        {
-
 
1422
                switch(mode)  // check mode
-
 
1423
                {
1179
                                cnt_entries_searched++;
1424
                        case 'a':
-
 
1425
                        case 'w': // if mode is write or append
1180
                        }
1426
                                // try to create the file
-
 
1427
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
-
 
1428
                                { // if it could not be created
-
 
1429
                                        fclose_(file);
-
 
1430
                                        file = NULL;
-
 
1431
                                }
-
 
1432
                                break;
1181
                        if(!retvalue)                                                                                                                   // file not found in this sector so take next sector.
1433
                        case 'r': // else opened for 'r'
1182
                        {
1434
                        default:  // of unsupported mode
1183
                                index = 0;
-
 
1184
                                sector_offset++;
1435
                                fclose_(file);
1185
                        }
1436
                                file = NULL;
-
 
1437
                                break; 
-
 
1438
                }
-
 
1439
                return(file);                  
1186
                }
1440
        }
1187
                while((cnt_entries_searched< PossibleRootEntries) && (!retvalue));
-
 
1188
 
1441
        // we should never come to this point
1189
        }
1442
        fclose_(file);
1190
        return(retvalue);                                                                                                                               // return 1 if file has been created otherwise return 0.
-
 
-
 
1443
        file = NULL;
1191
}
1444
        return(file);
1192
 
-
 
-
 
1445
}
1193
 
1446
 
1194
//________________________________________________________________________________________________________________________________________
1447
/****************************************************************************************************************************************************/
1195
// Funtion:     u16 SeekSubDirectory(s8 *fname)
-
 
1196
// 
1448
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1197
// Description: looks for the specified directory within the CWD.
1449
/*                                                                                                                                                                                                                                                                                                      */
1198
//                              
1450
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1199
// Returnvalue: If the specified directory was found the startcluster is returned. otherwise 0.
-
 
1200
//________________________________________________________________________________________________________________________________________
-
 
1201
 
-
 
1202
u16 SeekSubDirectory(s8 *fname)
-
 
1203
{
-
 
1204
        u16     index = 0;
1451
/*                                                                                                                                                                                                                                                                                                      */
1205
        u16     end_of_directory_not_reached = 0;                                                                               // the directory has been read completely without a result.
-
 
1206
        u8              i = 0;
-
 
1207
        u16     cluster_temp = 0;
-
 
1208
        s8 name[11]     = "           ";                       
-
 
1209
        File    file;
-
 
1210
 
-
 
1211
        SeperateFileName(fname,name);
-
 
1212
       
-
 
1213
        file.cluster_pointer = CWD;                                                                                                             // start looking for the file in the actual directory.
-
 
1214
        file.start_cluster   = CWD;                                                                                                             // start looking for the file in the actual directory.
-
 
1215
 
1452
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1216
                                                                                                                                                                        // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
1453
/****************************************************************************************************************************************************/
-
 
1454
s16     fflush_(File_t *file)
1217
        do
1455
{
1218
        {                                                                                                                                                               // search the next 16 rootentries in this sector of the roordirectory.          
1456
        DirEntry_t *dir;       
1219
                index=0;                                                                       
1457
       
1220
                SDC_GetSector((u32) file.cluster_pointer,file.buffer);                                          // Read the Rootdirectory.
1458
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1221
                DirectoryEntry = (struct DirEntry *)file.buffer;
1459
               
-
 
1460
        switch(file->Mode)
1222
 
1461
        {
1223
                while((!cluster_temp)&&(index<16))
1462
                case 'a':
1224
                {
1463
                case 'w':
1225
                        i=0;
-
 
-
 
1464
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?             
1226
                        if(DirectoryEntry[index].name[0] != 0xe5)                                                               // ignore deleted items.
1465
                        {
1227
                        {
1466
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer 
1228
                                while((i<=10)&&(DirectoryEntry[index].name[i] == name[i]))
1467
                                {
1229
                                {
-
 
1230
                                        i++;
1468
                                        Fat16_Deinit();
1231
                                }
1469
                                        return(EOF);   
-
 
1470
                                }                                      
-
 
1471
                        }
-
 
1472
                        file->SectorInCache     = file->DirectorySector;
1232
                        }
1473
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
-
 
1474
                        {
1233
 
1475
                                Fat16_Deinit();
1234
                        if((i==11) && (DirectoryEntry[index].attribute & _DIRECTORY))                   // entry found!! -> reading startcluster of entry from offset 26.
1476
                                return(EOF);    
-
 
1477
                        }
1235
                        {
1478
                       
-
 
1479
                        dir = (DirEntry_t *)file->Cache;
-
 
1480
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
-
 
1481
                        dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime);         // update date time
-
 
1482
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
-
 
1483
                        {
-
 
1484
                                Fat16_Deinit();
1236
                                cluster_temp = (u16)DirectoryEntry[index].startcluster;                                                        
1485
                                return(EOF);
1237
                        }
-
 
1238
                        index++;
1486
                        }
1239
                }
1487
                        break;
-
 
1488
                case 'r':
-
 
1489
                default:
-
 
1490
                        return(EOF);
-
 
1491
                        break;
-
 
1492
 
-
 
1493
        }
-
 
1494
        return(0);
-
 
1495
}
-
 
1496
 
1240
                if(!cluster_temp)                                                                                                                       // file not found in this sector so take next sector.
1497
/****************************************************************************************************************************************/
-
 
1498
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1241
                {
1499
/*                                                                                                                                                                                                                                                                              */
1242
                        end_of_directory_not_reached = GetNextCluster(&file);
1500
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1243
                }
1501
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1244
        }
-
 
1245
        while((end_of_directory_not_reached) && (!cluster_temp));
1502
/*                                                                                                                                                                                                                                                                              */
-
 
1503
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1246
        return(cluster_temp);
1504
/****************************************************************************************************************************************/
1247
}
1505
s16 fclose_(File_t *file)
-
 
1506
{
1248
 
1507
        s16 returnvalue = EOF;
-
 
1508
 
1249
 
1509
        if(file == NULL) return(returnvalue);
1250
 
-
 
-
 
1510
        returnvalue = fflush_(file);
-
 
1511
        UnlockFilePointer(file);
-
 
1512
        return(returnvalue);
-
 
1513
}
1251
//________________________________________________________________________________________________________________________________________
1514
 
1252
// Funtion:     u8 mkdir_(u8 *)
1515
/********************************************************************************************************************************************/
-
 
1516
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1253
// 
1517
/*                                                                                                                                                                                                                                                                                      */
-
 
1518
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
-
 
1519
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
-
 
1520
/*                                                                                                                                                                                                                                                                                      */
-
 
1521
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1254
// Description: This function checks if the directory to be created already exists. If not the directory will be created.
1522
/********************************************************************************************************************************************/
-
 
1523
s16 fgetc_(File_t *file)
1255
//                              
1524
{      
1256
//                              
1525
        s16 c = EOF;
1257
// returnvalue: 1 if the directory could be created.
1526
        u32 curr_sector;
1258
//________________________________________________________________________________________________________________________________________
1527
       
1259
 
-
 
1260
u8      mkdir_(s8 *fname)
-
 
1261
{
1528
        if( (!Partition.IsValid) || (file == NULL)) return(c);
-
 
1529
        // if the end of the file is not reached, get the next character.
1262
        u8 retvalue = 0;
1530
        if((0 < file->Size) && ((file->Position+1) < file->Size) )                                                             
1263
       
1531
        {
1264
        retvalue = SeekSubDirectory(fname);                                                                                             // check wether the specified directory already exists.
-
 
1265
       
-
 
1266
        if(!retvalue)
1532
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1267
        {
-
 
1268
                CreateSubDirectory(fname);                                                                                                      // if directory doesn't exist, create it.
-
 
1269
                retvalue = 1;
1533
                curr_sector += file->SectorOfCurrCluster;                      
1270
        }
1534
       
1271
        else
-
 
1272
        {
1535
                if(file->SectorInCache != curr_sector)
1273
                retvalue = 0;
-
 
-
 
1536
                {
1274
        }
1537
                        file->SectorInCache = curr_sector;
1275
       
1538
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
-
 
1539
                        {
1276
        return(retvalue);
1540
                                Fat16_Deinit();
1277
}
-
 
1278
 
-
 
1279
 
1541
                                return(c);
1280
//________________________________________________________________________________________________________________________________________
-
 
1281
// Funtion:     u8 chdir_(u8 *)
-
 
1282
// 
-
 
1283
// Description: This function changes the CWD to the directory specified.
-
 
1284
//                              
-
 
1285
//                              
-
 
1286
// returnvalue: 1 if the directory could be changed.
1542
                        }              
1287
//________________________________________________________________________________________________________________________________________
-
 
1288
 
1543
                }      
1289
u8      chdir_(s8 *fname)
-
 
1290
{
1544
                c = (s16) file->Cache[file->ByteOfCurrSector];
1291
        u8      retvalue = 0;
-
 
1292
        s8  name[11] = {"           "};
-
 
1293
       
-
 
1294
        u32 ultemp = 0;
1545
                file->Position++;                                                                       // increment file position
1295
 
1546
                file->ByteOfCurrSector++;                                                       // goto next byte in sector             
1296
        SeperateFileName(fname,name);  
1547
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1297
       
1548
                {
1298
        ultemp = (u32)SeekSubDirectory(name);
1549
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1299
        if(ultemp >= 2)
1550
                        file->SectorOfCurrCluster++;                                    //      next sector
-
 
1551
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
-
 
1552
                        {
1300
        {
1553
                               
1301
                ultemp -=2;                                                                                                                                     // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
1554
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1302
                ultemp *= SectorsPerCluster;                                                                                            // Calculate relative sectorindex of first datacluster.
1555
                                {
1303
                ultemp += FirstDataCluster;
-
 
1304
                CWD = ultemp;
1556
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
-
 
1557
                                }
1305
                retvalue = 1;
1558
                                else // the last cluster was allready reached
1306
        }
-
 
1307
        else
1559
                                {
1308
        {
-
 
-
 
1560
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
-
 
1561
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1309
                CWD = RootDirectory;
1562
                                }
1310
                retvalue = 1;
1563
                        }
1311
        }
-
 
1312
 
1564
                }
1313
        return(retvalue);
1565
        }
1314
}
-
 
1315
 
-
 
1316
 
-
 
1317
//________________________________________________________________________________________________________________________________________
1566
        return(c);
1318
// Funtion:     u8 FindItem(s8 *fname, Find *)
-
 
1319
// 
-
 
1320
// Description: finds an item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
-
 
-
 
1567
}
1321
//                              
1568
 
1322
// Returnvalue: If an item was found this function returns '1' else '0'.
1569
/********************************************************************************************************************************************/
1323
//________________________________________________________________________________________________________________________________________
1570
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1324
 
-
 
1325
u8 FindItem(Find *item)
-
 
1326
{
-
 
1327
        u16     index = 0;
1571
/*                                                                                                                                                                                                                                                                                      */
1328
        u16     end_of_directory_not_reached = 0;                                                                               // the directory has been read completely without a result.
-
 
1329
        u8              i = 0;
-
 
1330
        u8              readpointer = 0;
-
 
1331
        u8              writepointer = 0;
1572
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
-
 
1573
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1332
        u8              retvalue = 0;
1574
/*                                                                                                                                                                                                                                                                                      */
-
 
1575
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1333
        File    file;
1576
/********************************************************************************************************************************************/
-
 
1577
s16 fputc_(const s8 c, File_t *file)
-
 
1578
{      
1334
 
1579
        u32 curr_sector  = 0;
-
 
1580
       
1335
       
1581
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1336
        file.cluster_pointer = item->cluster_pointer;
1582
 
-
 
1583
        // If file position equals to file size, then the end of file has reached.
1337
        file.start_cluster   = item->cluster_pointer;                                  
1584
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR 
1338
        index                            = item->directory_index;
1585
        // and a new cluster should be appended.
1339
                                                                                                                                                                        // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
1586
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1340
        do
1587
        {
1341
        {                                                                                                                                                               // search the next 16 rootentries in this sector of the roordirectory.          
1588
                if(!AppendCluster(file)) return(EOF);
1342
                SDC_GetSector((u32) file.cluster_pointer,file.buffer);                                          // Read the Rootdirectory.
1589
        }
1343
                DirectoryEntry = (struct DirEntry *)file.buffer;
1590
 
1344
 
1591
        curr_sector  = file->FirstSectorOfCurrCluster;
1345
                while((!retvalue)&&(index<16))
1592
        curr_sector += file->SectorOfCurrCluster;
1346
                {
1593
        if(file->SectorInCache != curr_sector)
1347
                        i=0;                   
1594
        {
1348
                        if(DirectoryEntry[index].name[0] != 0xe5)                                                               // ignore deleted items.
1595
                file->SectorInCache = curr_sector;
1349
                        {
1596
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1350
                                while((i<=10)&&((DirectoryEntry[index].name[i] == item->searchstring[i]) || (item->searchstring[i]=='*') || item->searchstring[i]=='?'))
1597
                {
1351
                                {
1598
                        Fat16_Deinit();
1352
                                        i++;
1599
                        return(EOF);
1353
                                }
1600
                }                      
1354
                        }
1601
        }
-
 
1602
 
-
 
1603
        file->Cache[file->ByteOfCurrSector] = (u8)c;                    // write databyte into the buffer. The byte will be written to the device at once
-
 
1604
        if(file->Size == file->Position) file->Size++;          // a character has been written to the file so the size is incremented only when the character has been added at the end of the file.
1355
 
1605
        file->Position++;                                                                       // the actual positon within the file.
-
 
1606
        file->ByteOfCurrSector++;                                                       // goto next byte in sector 
1356
                        if((i==11) && (DirectoryEntry[index].attribute & item->attribute))
1607
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1357
                        {
1608
        {       // save the sector to the sd-card
1358
                                for(readpointer=0;readpointer<=10;readpointer++)
1609
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1359
                                {
-
 
1360
                                        if(DirectoryEntry[index].name[readpointer] != ' ')
1610
                {
1361
                                        {
-
 
1362
                                                item->name[writepointer] = DirectoryEntry[index].name[readpointer];     // copy the name of the item found to the find_structure.
1611
                        Fat16_Deinit();
1363
                                                writepointer++;
1612
                        return(EOF);
-
 
1613
                }
-
 
1614
                file->ByteOfCurrSector = 0;                                             //  reset byte location
1364
                                        }
1615
                file->SectorOfCurrCluster++;                                    //      next sector
1365
                                        else if((readpointer==7) && (DirectoryEntry[index].attribute == _FILE)) // if the item found is a file
1616
                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
-
 
1617
                {
1366
                                        {
1618
                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
-
 
1619
                        { // if current cluster was the last cluster of the file
1367
                                                if(DirectoryEntry[index].name[readpointer] != ' ')
1620
                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1368
                                                {
1621
                                {
1369
                                                        item->name[writepointer] = DirectoryEntry[index].name[readpointer];     // copy the name of the item found to the find_structure.
-
 
1370
                                                        writepointer++;
-
 
1371
                                                }
1622
                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1372
                                                item->name[writepointer] = '.';                                                 // then seperate the name and the extension by a '.' at index 8.                                                
1623
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1373
                                                writepointer++;
1624
                                        return(EOF);
1374
                                        }
1625
                                }
1375
                                }
-
 
1376
                                item->startcluster = (u16)DirectoryEntry[index].startcluster;                                                  
-
 
1377
                                item->directory_index = ++index;
-
 
1378
                                item->cluster_pointer = file.cluster_pointer;
1626
                        }
1379
                                retvalue = 1;
-
 
1380
                        }
-
 
1381
                        index++;
-
 
1382
                }
-
 
1383
                if(!retvalue)                                                                                                                           // file not found in this sector so take next sector.
1627
                        else // next cluster
1384
                {
1628
                        {
1385
                        end_of_directory_not_reached = GetNextCluster(&file);
1629
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1386
                }
-
 
1387
                index = 0;
1630
                        }                                              
1388
        }
-
 
1389
        while((end_of_directory_not_reached) && (!retvalue));
-
 
1390
       
-
 
1391
        return(retvalue);      
1631
                }
1392
}
-
 
1393
 
-
 
1394
 
-
 
1395
//________________________________________________________________________________________________________________________________________
-
 
1396
// Funtion:     u8 findfirst(s8 *fname, Find *)
-
 
1397
// 
-
 
1398
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
-
 
1399
//                              
-
 
1400
// Returnvalue: If an item was found this function returns '1' else '0'.
-
 
1401
//________________________________________________________________________________________________________________________________________
-
 
1402
 
-
 
1403
u8 findfirst_(s8 *fname, Find *item, u8 attribute)
-
 
1404
{
-
 
1405
        u8 retvalue = 0;
1632
        }
1406
        u8 i = 0;
-
 
1407
 
-
 
1408
        for(i=0;i<=11;i++)
-
 
1409
        {
-
 
1410
                item->searchstring[i] = '*';                                                                                            // initialise the searchstring with wildcards.
-
 
1411
                item->name[i] = 0;
1633
        return(0);
1412
        }
-
 
1413
 
-
 
1414
        SeperateFileName(fname,item->searchstring);
-
 
1415
       
-
 
1416
        item->cluster_pointer = CWD;                                                                                                    // findfirst_ starts at the beginning of the cwd.
-
 
-
 
1634
}
-
 
1635
 
-
 
1636
 
-
 
1637
/****************************************************************************************************************************************/
-
 
1638
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
-
 
1639
/*                                                                                                                                                                                                                                                                              */
-
 
1640
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
-
 
1641
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1417
        item->directory_index = 0;
1642
/*                                                                                                                                                                                                                                                                              */
1418
        item->attribute = attribute;
1643
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
-
 
1644
/****************************************************************************************************************************************/
-
 
1645
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1419
       
1646
{
-
 
1647
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1420
        retvalue = FindItem(item);
1648
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
-
 
1649
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1421
 
-
 
1422
        return(retvalue);      
-
 
1423
}
-
 
1424
 
-
 
1425
 
-
 
1426
//________________________________________________________________________________________________________________________________________
1650
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1427
// Funtion:     u8 findnext(Find *)
-
 
1428
// 
1651
        s16 c; 
1429
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
1652
 
1430
//                              
1653
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1431
// Returnvalue: If an item was found this function returns '1' else '0'.
1654
 
1432
//________________________________________________________________________________________________________________________________________
-
 
1433
 
-
 
1434
u8 findnext_(Find *item)
1655
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1435
{
1656
       
-
 
1657
        while((object_cnt < count) && success)
-
 
1658
        {
-
 
1659
                object_size = size;
-
 
1660
                while((size > 0) && success)
-
 
1661
                {
1436
        u8 retvalue = 0;
1662
                        c = fgetc_(file);
-
 
1663
                        if(c != EOF)
-
 
1664
                        {
-
 
1665
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
-
 
1666
                                pbuff++;
1437
        u8 i = 0;
1667
                                size--;
1438
 
1668
                        }
1439
        for(i=0;i<=11;i++)                                                                                                                              // copy the name of the searched item to the findstructure.
1669
                        else // error or end of file reached
1440
        {
1670
                        {
1441
                item->name[i] = 0;
1671
                                success = 0;   
1442
        }
1672
                        }
1443
 
1673
                }
1444
        retvalue = FindItem(item);                                                                                                              // search the item.
1674
                if(success) object_cnt++;
1445
 
1675
        }              
1446
        return(retvalue);      
1676
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1447
}
1677
}
1448
 
1678
 
1449
 
-
 
1450
 
1679
 
-
 
1680
/****************************************************************************************************************************************/
1451
//________________________________________________________________________________________________________________________________________
1681
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1452
// Funtion:     u8 fdelete(s8 *fname)
-
 
1453
// 
1682
/*                                                                                                                                                                                                                                                                              */
1454
// Description: Deletes the file specified by fname.
-
 
-
 
1683
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1455
//                              
1684
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
-
 
1685
/*                                                                                                                                                                                                                                                                              */
1456
// Returnvalue: 
1686
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1457
//________________________________________________________________________________________________________________________________________
-
 
1458
 
1687
/****************************************************************************************************************************************/
1459
u8 fdelete_(s8 *fname)
1688
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
-
 
1689
{
-
 
1690
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1460
{
1691
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
-
 
1692
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1461
        u8 retvalue = 0;
1693
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1462
        Find item;
1694
        s16 c; 
1463
       
-
 
1464
        retvalue = findfirst_(fname,&item, _FILE);                                                                              // look for the item to be deleted.
-
 
1465
 
-
 
1466
        if(retvalue);                                                                                                                                   // item found?
1695
 
-
 
1696
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
-
 
1697
 
-
 
1698
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
-
 
1699
       
1467
        {
1700
        while((object_cnt < count) && success)
-
 
1701
        {
-
 
1702
                object_size = size;
1468
                DeleteClusterChain(item.startcluster);                                                                          // delete all fatentries of the item. 
1703
                while((size > 0) && success)
1469
                DeleteDirectoryEntry(&item);                                                                                            // free the directoryentry.
1704
                {
-
 
1705
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
-
 
1706
                        if(c != EOF)
1470
       
1707
                        {
1471
                do
1708
                                pbuff++;
1472
                {
-
 
1473
                        retvalue = findnext_(&item);
1709
                                size--;
1474
                        if(retvalue)
1710
                        }
1475
                        {
1711
                        else
1476
                                DeleteClusterChain(item.startcluster);                                                          // delete all fatentries of the item. 
1712
                        {
1477
                                DeleteDirectoryEntry(&item);                                                                            // free the directoryentry.                             
1713
                                success = 0;
1478
                        }
1714
                        }
1479
                }
1715
                }
1480
                while(retvalue);       
1716
                if(success) object_cnt++;
1481
        }
1717
        }              
1482
 
1718
       
1483
        return(retvalue);      
1719
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1484
}
1720
}                                                                                                                                                                              
1485
 
1721
 
1486
 
1722
 
-
 
1723
/****************************************************************************************************************************************/
1487
//________________________________________________________________________________________________________________________________________
1724
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1488
// Funtion:     u8 rmdir(s8 *fname)
-
 
1489
// 
1725
/*                                                                                                                                                                                                                                                                              */
1490
// Description: Deletes the directory specified by dname.
-
 
1491
//                              
1726
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
-
 
1727
/*                                                                                                                                                                                                                                                                              */
1492
// Returnvalue: 
1728
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1493
//________________________________________________________________________________________________________________________________________
-
 
1494
 
1729
/****************************************************************************************************************************************/
1495
u8 rmdir_(s8 *dname)
1730
s16 fputs_(const s8 *string, File_t *file)
1496
{
1731
{
1497
        u8 retvalue = 0;
1732
        u8 i=0;
1498
        Find item;
-
 
1499
       
-
 
1500
        retvalue = findfirst_(dname,&item, _DIRECTORY);                                                                 // look for the item to be deleted.
-
 
1501
 
-
 
1502
        if(retvalue);                                                                                                                                           // item found?
-
 
1503
        {
1733
        s16 c = 0;
1504
                DeleteClusterChain(item.startcluster);                                                                                  // delete all fatentries of the item. 
-
 
-
 
1734
       
1505
                DeleteDirectoryEntry(&item);                                                                                                    // free the directoryentry.
1735
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
1506
       
1736
 
1507
                do
-
 
1508
                {
1737
        while((string[i] != 0)&& (c != EOF))
1509
                        retvalue = findnext_(&item);
-
 
1510
                        if(retvalue)
-
 
1511
                        {
-
 
1512
                                DeleteClusterChain(item.startcluster);                                                                  // delete all fatentries of the item. 
-
 
1513
                                DeleteDirectoryEntry(&item);                                                                                    // free the directoryentry.                             
-
 
1514
                        }
1738
        {
1515
                }
-
 
1516
                while(retvalue);       
1739
                c = fputc_(string[i], file);
1517
        }
1740
                i++;
-
 
1741
        }
-
 
1742
        return(c);
-
 
1743
}
-
 
1744
 
-
 
1745
/****************************************************************************************************************************************/
-
 
1746
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
-
 
1747
/*                                                                                                                                                                                                                                                                              */
-
 
1748
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
-
 
1749
/*                                                                                                                                                                                                                                                                              */
-
 
1750
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
-
 
1751
/****************************************************************************************************************************************/
-
 
1752
u8 * fgets_(s8 *string, s16 length, File_t *file)
-
 
1753
{
-
 
1754
        u8 *pbuff;
-
 
1755
        s16 c = 0;
-
 
1756
       
-
 
1757
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length = 0)) return (0);
-
 
1758
        pbuff = string;
-
 
1759
        while(length > 1)                                                       // read the count-1 characters from the file to the string.
-
 
1760
        {
-
 
1761
                c = fgetc_(file);                                               // read a character from the opened file.
-
 
1762
                switch(c)
-
 
1763
                {
-
 
1764
                        case 0x0A:
1518
 
1765
                                c = 0;                                                  // set string terminator
1519
        return(retvalue);      
1766
                                length = 1;                                             // stop loop
-
 
1767
                                break;
1520
}
1768
                       
1521
 
1769
                        case EOF:
-
 
1770
                                c = 0;                                                  // set string terminator
-
 
1771
                                length = 1;                                             // stop loop
1522
 
1772
                                break; 
1523
//________________________________________________________________________________________________________________________________________
1773
                }
1524
// Funtion:     u16 feof_(File *file)
-
 
-
 
1774
                *pbuff = (u8)c;                                                 // copy byte to string
-
 
1775
                length--;
-
 
1776
                pbuff++;
-
 
1777
        }
-
 
1778
        return(string);
-
 
1779
}
-
 
1780
 
-
 
1781
/****************************************************************************************************************************************/
-
 
1782
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
-
 
1783
/*                                                                                                                                                                                                                                                                              */
-
 
1784
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
-
 
1785
/*                                                                                                                                                                                                                                                                              */
-
 
1786
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
-
 
1787
/****************************************************************************************************************************************/
-
 
1788
u8 fexist_(const s8* filename)
-
 
1789
{
-
 
1790
        u8 exist = 0;
-
 
1791
        File_t *file = 0;
-
 
1792
        file = LockFilePointer();
-
 
1793
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
-
 
1794
        UnlockFilePointer(file);
-
 
1795
        return(exist);
-
 
1796
}
-
 
1797
 
-
 
1798
/****************************************************************************************************************************************/
1525
// 
1799
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1526
// Description: This function checks wether the end of the file has been reached.
1800
/*                                                                                                                                                                                                                                                                              */
1527
//                              
1801
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1528
// Returnvalue: 0 if the end of the file was not reached otherwise 1. 
1802
/*                                                                                                                                                                                                                                                                              */
1529
//________________________________________________________________________________________________________________________________________
1803
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1530
 
1804
/****************************************************************************************************************************************/
1531
u16 feof_(File *file)
1805
u8 feof_(File_t *file)
1532
{      
1806
{      
1533
        if(((file->fileposition)+1) < (file->filesize))
1807
        if(((file->Position)+1) < (file->Size))
1534
        {
1808
        {
1535
                return(0);
1809
                return(0);
1536
        }
1810
        }
1537
        else
1811
        else
1538
        {
1812
        {
1539
                return(1);     
1813
                return(1);     
1540
        }
1814
        }
1541
}
1815
}
-
 
1816
 
-
 
1817
 
1542
 
1818