Subversion Repositories NaviCtrl

Rev

Rev 41 | Rev 89 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 41 Rev 88
Line 5... Line 5...
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
Line 50... Line 50...
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>
57
#include <stdio.h>
58
#include "91x_lib.h"
58
#include "91x_lib.h"
59
#include "timer.h"
59
#include "timer.h"
60
#include "fat16.h"
60
#include "fat16.h"
61
#include "sdc.h"
61
#include "sdc.h"
62
#include "uart1.h"
62
#include "uart1.h"
Line 63... Line 63...
63
 
63
 
64
 
64
 
65
//________________________________________________________________________________________________________________________________________
65
//________________________________________________________________________________________________________________________________________
66
// Module name:                 fat16.c 
66
// Module name:                 fat16.c
67
// Compiler used:               avr-gcc 3.4.5
67
// Compiler used:               avr-gcc 3.4.5
68
// Last Modifikation:   16.06.2008
68
// Last Modifikation:   16.06.2008
69
// Version:                             2.00
69
// Version:                             2.00
70
// Authors:                             Stephan Busker & Gregor Stobrawa        
70
// Authors:                             Stephan Busker & Gregor Stobrawa
71
// Description:                 Source files for FAT16 implementation with read and write-access
71
// Description:                 Source files for FAT16 implementation with read and write-access
72
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
72
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
73
//........................................................................................................................................
73
//........................................................................................................................................
74
// Functions:                   extern s16              Fat16_Init(void);
74
// Functions:                   extern s16              Fat16_Init(void);
75
//                                              extern s16              Fat16_Deinit(void);             
75
//                                              extern s16              Fat16_Deinit(void);
76
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
76
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
77
//                                              extern s16              fclose_(File_t *File);
77
//                                              extern s16              fclose_(File_t *File);
78
//                                              extern s16              fflush_(File_t *File);
78
//                                              extern s16              fflush_(File_t *File);
79
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
79
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
80
//                                              extern s16              fgetc_(File_t *File);
80
//                                              extern s16              fgetc_(File_t *File);
81
//                                              extern s16              fputc_(u8 c, File_t *File);
81
//                                              extern s16              fputc_(u8 c, File_t *File);
82
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File); 
82
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File);
83
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
83
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
84
//                                              extern s16              fputs_(const u8 *string, File_t *File);
84
//                                              extern s16              fputs_(const u8 *string, File_t *File);
85
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
85
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
86
//........................................................................................................................................
86
//........................................................................................................................................
87
// ext. functions:              extern SD_Result_t SDC_Init(void;)
87
// ext. functions:              extern SD_Result_t SDC_Init(void;)
88
//                                              extern SD_Result_t SDC_Deinit(void);
88
//                                              extern SD_Result_t SDC_Deinit(void);
89
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);            
89
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);
90
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
90
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
91
//........................................................................................................................................
91
//........................................................................................................................................
92
//
92
//
Line 104... Line 104...
104
*/
104
*/
Line 105... Line 105...
105
 
105
 
106
 
106
 
107
/*
107
/*
108
________________________________________________________________________________________________________________________________________
108
________________________________________________________________________________________________________________________________________
109
 
109
 
Line 110... Line 110...
110
        Structure of an partition entry                        
110
        Structure of an partition entry
111
________________________________________________________________________________________________________________________________________
111
________________________________________________________________________________________________________________________________________
112
 
112
 
Line 120... Line 120...
120
        u8      Type;                                           // Type of Partition (See List Below)
120
        u8      Type;                                           // Type of Partition (See List Below)
121
        u8      EndHead;                                        // End of Partition - Head
121
        u8      EndHead;                                        // End of Partition - Head
122
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
122
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
123
        u32     NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
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
124
        u32     NoSectorsPartition      ;               // Number of Sectors in the Partition
125
} __attribute__((packed)) PartitionEntry_t;
125
} __attribute__((packed)) PartitionEntry_t;
Line 126... Line 126...
126
 
126
 
127
/*
127
/*
Line 128... Line 128...
128
Coding of Cylinder/Sector words
128
Coding of Cylinder/Sector words
129
 
129
 
130
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
130
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
Line 131... Line 131...
131
Sector is 5 bits:  [5:0] at [5:0]  
131
Sector is 5 bits:  [5:0] at [5:0]
132
*/
132
*/
133
 
133
 
Line 160... Line 160...
160
#define PART_TYPE_BBT                           0xFF
160
#define PART_TYPE_BBT                           0xFF
Line 161... Line 161...
161
 
161
 
162
 
162
 
163
/*
163
/*
164
________________________________________________________________________________________________________________________________________
164
________________________________________________________________________________________________________________________________________
165
 
165
 
Line 166... Line 166...
166
        Structure of the MasterBootRecord                      
166
        Structure of the MasterBootRecord
167
________________________________________________________________________________________________________________________________________
167
________________________________________________________________________________________________________________________________________
168
 
168
 
169
        Master Boot Record is 512 bytes long
169
        Master Boot Record is 512 bytes long
170
        The Master Boot Record is the same for pretty much all Operating Systems.
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
171
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
172
*/
172
*/
173
typedef struct
173
typedef struct
174
{
174
{
175
        u8                              ExecutableCode[446];    // 446 bytes for machine start code     
175
        u8                              ExecutableCode[446];    // 446 bytes for machine start code
176
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1                                       
176
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1
177
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2                                       
177
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2
178
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3                                       
178
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3
Line 179... Line 179...
179
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4                                       
179
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4
180
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)   
180
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)
181
} __attribute__((packed)) MBR_Entry_t;
181
} __attribute__((packed)) MBR_Entry_t;
182
 
182
 
183
 
183
 
Line 184... Line 184...
184
/*
184
/*
185
________________________________________________________________________________________________________________________________________
185
________________________________________________________________________________________________________________________________________
186
 
186
 
187
        Structure of the VolumeBootRecord                      
187
        Structure of the VolumeBootRecord
188
________________________________________________________________________________________________________________________________________
188
________________________________________________________________________________________________________________________________________
189
 
189
 
190
        The Volume Boot Record is 512 bytes long
190
        The Volume Boot Record is 512 bytes long
191
        This information is located in the first sector of every partition.
191
        This information is located in the first sector of every partition.
192
*/
192
*/
193
typedef struct
193
typedef struct
194
{
194
{
195
        u8  JumpCode[3];                        // Jump Code + NOP
195
        u8  JumpCode[3];                        // Jump Code + NOP
196
        s8  OEMName[8];                         // OEM Name             
196
        s8  OEMName[8];                         // OEM Name
197
        u16 BytesPerSector;                     // Bytes Per Sector
197
        u16 BytesPerSector;                     // Bytes Per Sector
198
        u8  SectorsPerCluster;          // Sectors Per Cluster
198
        u8  SectorsPerCluster;          // Sectors Per Cluster
199
        u16 ReservedSectors;            // Reserved Sectors
199
        u16 ReservedSectors;            // Reserved Sectors
200
        u8  NoFATCopies;                        // Number of Copies of FAT
200
        u8  NoFATCopies;                        // Number of Copies of FAT
Line 209... Line 209...
209
        u16     DriveNo;                                // Logical Drive Number of Partition
209
        u16     DriveNo;                                // Logical Drive Number of Partition
210
        u8  ExtendedSig;                        // Extended Signature (0x29)
210
        u8  ExtendedSig;                        // Extended Signature (0x29)
211
        u32 SerialNo;                           // Serial Number of the Partition
211
        u32 SerialNo;                           // Serial Number of the Partition
212
        s8  VolumeName[11];                     // Volume Name of the Partititon
212
        s8  VolumeName[11];                     // Volume Name of the Partititon
213
        s8  FATName[8];                         // FAT Name (FAT16)
213
        s8  FATName[8];                         // FAT Name (FAT16)
214
        u8  ExecutableCode[446];        // 446 bytes for machine start code     
214
        u8  ExecutableCode[446];        // 446 bytes for machine start code
215
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)        
215
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)
216
} __attribute__((packed)) VBR_Entry_t;
216
} __attribute__((packed)) VBR_Entry_t;
Line 217... Line 217...
217
 
217
 
218
 
218
 
Line 219... Line 219...
219
 
219
 
220
/*
220
/*
Line 221... Line 221...
221
________________________________________________________________________________________________________________________________________
221
________________________________________________________________________________________________________________________________________
222
 
222
 
223
        Structure of an directory entry                
223
        Structure of an directory entry
Line 250... Line 250...
250
#define ATTR_ARCHIVE            0x20    // file is new or modified
250
#define ATTR_ARCHIVE            0x20    // file is new or modified
Line 251... Line 251...
251
 
251
 
252
 
252
 
253
/*
253
/*
254
________________________________________________________________________________________________________________________________________
254
________________________________________________________________________________________________________________________________________
255
 
255
 
256
        Structure of an entry within the fileallocationtable.                  
256
        Structure of an entry within the fileallocationtable.
257
________________________________________________________________________________________________________________________________________
257
________________________________________________________________________________________________________________________________________
258
*/
258
*/
259
typedef struct
259
typedef struct
Line 270... Line 270...
270
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
270
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
271
#define FAT16_CLUSTER_BAD                       0xFFF7
271
#define FAT16_CLUSTER_BAD                       0xFFF7
272
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
272
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
273
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
273
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
Line 274... Line 274...
274
 
274
 
275
/*****************************************************************************************************************************************/
275
/*****************************************************************************************************************************************/
276
/*                                                                                                                                                                                                                                                                               */
276
/*                                                                                                                                                                                                                                                                               */
277
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
277
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
278
/*                                                                                                                                                                                                                                                                               */
278
/*                                                                                                                                                                                                                                                                               */
Line 282... Line 282...
282
#define DIRENTRY_SIZE                           32              //bytes
282
#define DIRENTRY_SIZE                           32              //bytes
283
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
283
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
284
#define FAT16_BYTES                                     2
284
#define FAT16_BYTES                                     2
285
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
285
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
Line 286... Line 286...
286
 
286
 
287
#define FSTATE_UNUSED   0                                       
287
#define FSTATE_UNUSED   0
Line 288... Line 288...
288
#define FSTATE_USED             1
288
#define FSTATE_USED             1
289
 
289
 
290
typedef struct
290
typedef struct
Line 339... Line 339...
339
{
339
{
340
        u8 i;
340
        u8 i;
341
        File_t * File = 0;
341
        File_t * File = 0;
342
        for(i = 0; i < FILE_MAX_OPEN; i++)
342
        for(i = 0; i < FILE_MAX_OPEN; i++)
343
        {
343
        {
344
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one                                                                                  
344
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one
345
                {
345
                {
346
                        File = &FilePointer[i];                                         // set pointer to that entry             
346
                        File = &FilePointer[i];                                         // set pointer to that entry
347
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
347
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
348
                        break;
348
                        break;
349
                }
349
                }
350
        }
350
        }
351
        return(File);
351
        return(File);
Line 364... Line 364...
364
        if(file == NULL) return(0);
364
        if(file == NULL) return(0);
365
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
365
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
366
        {
366
        {
367
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
367
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
368
                {
368
                {
369
                        file->State = FSTATE_UNUSED;                                                                                                   
369
                        file->State = FSTATE_UNUSED;
370
                        file->FirstSectorOfFirstCluster = 0;                    // Sectorpointer to the first sector of the first datacluster of the file. 
370
                        file->FirstSectorOfFirstCluster = 0;                    // Sectorpointer to the first sector of the first datacluster of the file.
371
                        file->FirstSectorOfCurrCluster  = 0;
371
                        file->FirstSectorOfCurrCluster  = 0;
372
                        file->SectorOfCurrCluster               = 0;                    // Pointer to the cluster which is edited at the moment.
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).
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).
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)
375
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
Line 377... Line 377...
377
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
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.
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.
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.
380
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
381
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
381
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
382
                        file = NULL;
382
                        file = NULL;
383
                        return(1);
383
                        return(1);
384
                }
384
                }
385
        }
385
        }
386
        return(0);
386
        return(0);
387
}
387
}
Line 399... Line 399...
399
{
399
{
400
        s8* subpath = NULL;
400
        s8* subpath = NULL;
401
        u8 readpointer  = 0;
401
        u8 readpointer  = 0;
402
        u8 writepointer = 0;
402
        u8 writepointer = 0;
Line 403... Line 403...
403
 
403
 
404
        // search subpath from beginning of filepath                                    
404
        // search subpath from beginning of filepath
405
        subpath = NULL;
405
        subpath = NULL;
406
        readpointer     = 0;
406
        readpointer     = 0;
407
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
407
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
408
        while(subpath == NULL)  // search the filepath until a subpath was found.       
408
        while(subpath == NULL)  // search the filepath until a subpath was found.
409
        {
409
        {
410
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached 
410
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached
411
                {      
411
                {
412
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
412
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
413
                }
413
                }
414
                readpointer++;
414
                readpointer++;
Line 429... Line 429...
429
                        if(writepointer <= 8)
429
                        if(writepointer <= 8)
430
                        {
430
                        {
431
                                readpointer++;                                          // next character in filename
431
                                readpointer++;                                          // next character in filename
432
                                writepointer = 8;                                       // jump to start of extension
432
                                writepointer = 8;                                       // jump to start of extension
433
                        }
433
                        }
434
                        else return(NULL);                                              // dirbasename to long                                                          
434
                        else return(NULL);                                              // dirbasename to long
435
                }
435
                }
436
                else
436
                else
437
                {
437
                {
438
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
438
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
439
                        {
439
                        {
440
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
440
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
441
                        }
441
                        }
442
                        else
442
                        else
443
                        {
443
                        {
444
                                dirname[writepointer] = filepath[readpointer];
444
                                dirname[writepointer] = filepath[readpointer];
445
                        }      
445
                        }
446
                        readpointer++;
446
                        readpointer++;
447
                        writepointer++;
447
                        writepointer++;
448
                }
448
                }
449
        }
449
        }
450
        return(subpath);       
450
        return(subpath);
451
}
451
}
Line 452... Line 452...
452
 
452
 
453
 
453
 
Line 460... Line 460...
460
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
460
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
461
/****************************************************************************************************************************************/
461
/****************************************************************************************************************************************/
462
u32     Fat16ClusterToSector(u16 cluster)
462
u32     Fat16ClusterToSector(u16 cluster)
463
{
463
{
464
        if(!Partition.IsValid) return 0;
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 
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
466
        return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
467
}
467
}
Line 468... Line 468...
468
 
468
 
469
/****************************************************************************************************************************************/
469
/****************************************************************************************************************************************/
Line 497... Line 497...
497
        {
497
        {
498
                if(FilePointer[cnt].State == FSTATE_USED)
498
                if(FilePointer[cnt].State == FSTATE_USED)
499
                {
499
                {
500
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
500
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
501
                }
501
                }
502
                                                               
502
 
503
        }
503
        }
504
        SDC_Deinit();                   // uninitialize interface to sd-card
504
        SDC_Deinit();                   // uninitialize interface to sd-card
505
        Partition.IsValid = 0;  // mark data in partition structure as invalid
505
        Partition.IsValid = 0;  // mark data in partition structure as invalid
506
        return(returnvalue);
506
        return(returnvalue);
507
}
507
}
Line 513... Line 513...
513
/*                                      and stores the information in global variables.                                                                                                                                     */
513
/*                                      and stores the information in global variables.                                                                                                                                     */
514
/*                                                                                                                                                                                                                                                                          */
514
/*                                                                                                                                                                                                                                                                          */
515
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
515
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
516
/****************************************************************************************************************************************/
516
/****************************************************************************************************************************************/
517
u8 Fat16_Init(void)
517
u8 Fat16_Init(void)
518
{      
518
{
519
    u8  cnt     = 0;
519
    u8  cnt     = 0;
520
        u32     partitionfirstsector;
520
        u32     partitionfirstsector;
521
        VBR_Entry_t *VBR;              
521
        VBR_Entry_t *VBR;
522
        MBR_Entry_t *MBR;
522
        MBR_Entry_t *MBR;
523
        File_t *file;
523
        File_t *file;
524
        u8 result = 0;
524
        u8 result = 0;
Line 525... Line 525...
525
 
525
 
526
        SerialPutString("\r\n FAT16 init...");
526
        SerialPutString("\r\n FAT16 init...");
Line 527... Line 527...
527
        Partition.IsValid = 0;
527
        Partition.IsValid = 0;
528
 
528
 
529
        // declare the filepointers as unused.
529
        // declare the filepointers as unused.
530
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
530
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
531
        {
531
        {
532
                FilePointer[cnt].State = FSTATE_UNUSED;                                        
532
                FilePointer[cnt].State = FSTATE_UNUSED;
533
        }
533
        }
534
        // set current file pinter to first position in list
534
        // set current file pinter to first position in list
535
        file = &FilePointer[0];                                                                        
535
        file = &FilePointer[0];
536
       
536
 
537
        // try to initialise the sd-card.
537
        // try to initialise the sd-card.
538
        if(SD_SUCCESS != SDC_Init())                                                   
538
        if(SD_SUCCESS != SDC_Init())
539
        {  
539
        {
540
                SerialPutString("SD-Card could not be initialized.");
540
                SerialPutString("SD-Card could not be initialized.");
541
                result = 1;
541
                result = 1;
Line 542... Line 542...
542
                goto end;      
542
                goto end;
543
        }
543
        }
544
 
544
 
545
        // SD-Card is initialized successfully
545
        // SD-Card is initialized successfully
546
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
546
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
547
        {
547
        {
548
                SerialPutString("Error reading the MBR.");
548
                SerialPutString("Error reading the MBR.");
549
                result = 2;
549
                result = 2;
550
                goto end;      
550
                goto end;
551
        }
551
        }
552
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
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) ||
553
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
554
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
554
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
555
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
555
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
556
        {
556
        {
557
                // get sector offset 1st partition
557
                // get sector offset 1st partition
558
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
558
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
559
                // Start of Partition is the Volume Boot Sector
559
                // Start of Partition is the Volume Boot Sector
560
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
560
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
561
                {
561
                {
562
                        SerialPutString("Error reading the VBR.");
562
                        SerialPutString("Error reading the VBR.");
563
                        result = 3;
563
                        result = 3;
564
                        goto end;      
564
                        goto end;
565
                }                      
565
                }
566
        }
566
        }
567
        else  // maybe the medium has no partition assuming sector 0 is the vbr
567
        else  // maybe the medium has no partition assuming sector 0 is the vbr
568
        {
568
        {
569
                partitionfirstsector = 0;
569
                partitionfirstsector = 0;
570
        }
570
        }
571
       
571
 
572
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
572
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
573
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
573
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
574
        {
574
        {
575
                SerialPutString("VBR: Sector size not supported.");
575
                SerialPutString("VBR: Sector size not supported.");
576
                result = 4;
576
                result = 4;
577
                goto end;      
577
                goto end;
578
        }
578
        }
579
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
579
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
Line 580... Line 580...
580
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
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).
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.
582
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
583
 
583
 
584
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
584
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
585
        // Calculate the position of the FileAllocationTable: 
585
        // Calculate the position of the FileAllocationTable:
586
        // Start + # of Reserved Sectors
586
        // Start + # of Reserved Sectors
587
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors)); 
587
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
588
        // Calculate the position of the Rootdirectory: 
588
        // Calculate the position of the Rootdirectory:
589
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)                                                     
589
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
590
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
590
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
591
        // Calculate the position of the first datacluster:
591
        // Calculate the position of the first datacluster:
592
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)                
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
593
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
594
        // Calculate the last data sector
594
        // Calculate the last data sector
595
        if(VBR->NoSectors == 0)
595
        if(VBR->NoSectors == 0)
596
        {
596
        {
597
                SerialPutString("VBR: Bad number of sectors.");
597
                SerialPutString("VBR: Bad number of sectors.");
598
                result = 5;
598
                result = 5;
599
                goto end;      
599
                goto end;
600
        }
600
        }
Line 609... Line 609...
609
        Partition.IsValid = 1; // mark data in partition structure as valid
609
        Partition.IsValid = 1; // mark data in partition structure as valid
610
        result = 0;
610
        result = 0;
611
        end:
611
        end:
612
        if(result != 0) Fat16_Deinit();
612
        if(result != 0) Fat16_Deinit();
613
        else SerialPutString("ok");
613
        else SerialPutString("ok");
614
        return(result);
614
        return(result);
615
}
615
}
Line 616... Line 616...
616
 
616
 
Line 625... Line 625...
625
/****************************************************************************************************************************************/
625
/****************************************************************************************************************************************/
626
u8 ClearCurrCluster(File_t * file)
626
u8 ClearCurrCluster(File_t * file)
627
{
627
{
628
        u8 retvalue = 1;
628
        u8 retvalue = 1;
629
        u32 i;
629
        u32 i;
630
       
630
 
631
        if((!Partition.IsValid) || (file == NULL)) return(0);
631
        if((!Partition.IsValid) || (file == NULL)) return(0);
Line 632... Line 632...
632
 
632
 
633
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
633
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
634
        for(i = 0; i < Partition.SectorsPerCluster; i++)
634
        for(i = 0; i < Partition.SectorsPerCluster; i++)
635
        {
635
        {
636
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
636
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
637
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
637
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
638
                {
638
                {
639
                        Fat16_Deinit();
639
                        Fat16_Deinit();
640
                        retvalue = 0;
640
                        retvalue = 0;
641
                }
641
                }
642
        }
642
        }
643
        return(retvalue);      
643
        return(retvalue);
Line 644... Line 644...
644
}
644
}
645
 
645
 
646
/*****************************************************************************************************************************************/
646
/*****************************************************************************************************************************************/
Line 653... Line 653...
653
u16 GetNextCluster(File_t * file)
653
u16 GetNextCluster(File_t * file)
654
{
654
{
655
        u16 cluster = 0;
655
        u16 cluster = 0;
656
        u32 fat_byte_offset, sector, byte;
656
        u32 fat_byte_offset, sector, byte;
657
        Fat16Entry_t * fat;
657
        Fat16Entry_t * fat;
658
       
658
 
659
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
659
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
660
        // if sector is within the data area
660
        // if sector is within the data area
661
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
661
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
662
        {
662
        {
663
                // determine current file cluster
663
                // determine current file cluster
Line 674... Line 674...
674
                        file->SectorInCache = sector;                                           // update sector stored in buffer
674
                        file->SectorInCache = sector;                                           // update sector stored in buffer
675
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
675
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
676
                        {
676
                        {
677
                                Fat16_Deinit();
677
                                Fat16_Deinit();
678
                                return (cluster);
678
                                return (cluster);
679
                        }              
679
                        }
680
                }
680
                }
681
                // read the next cluster from cache
681
                // read the next cluster from cache
682
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
682
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
683
                cluster = fat->NextCluster;
683
                cluster = fat->NextCluster;
684
                // if last cluster fat entry 
684
                // if last cluster fat entry
685
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
685
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
686
                {
686
                {
687
                         cluster = 0;
687
                         cluster = 0;
688
                }
688
                }
689
                else
689
                else
690
                {
690
                {
691
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
691
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
692
                        file->SectorOfCurrCluster = 0;
692
                        file->SectorOfCurrCluster = 0;
693
                        file->ByteOfCurrSector = 0;
693
                        file->ByteOfCurrSector = 0;
694
                }
694
                }
695
        }      
695
        }
696
        return(cluster);
696
        return(cluster);
697
}
697
}
Line 698... Line 698...
698
 
698
 
Line 709... Line 709...
709
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
709
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
710
        u32     curr_sector;                            // current sector
710
        u32     curr_sector;                            // current sector
711
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
711
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
712
        u16     free_cluster    = 0;            // next free cluster number.
712
        u16     free_cluster    = 0;            // next free cluster number.
713
        Fat16Entry_t * fat;
713
        Fat16Entry_t * fat;
714
       
714
 
715
        if((!Partition.IsValid) || (file == NULL)) return(0);
715
        if((!Partition.IsValid) || (file == NULL)) return(0);
Line 716... Line 716...
716
 
716
 
717
        // start searching for an empty cluster at the beginning of the fat.
717
        // start searching for an empty cluster at the beginning of the fat.
718
        fat_sector = 0;
718
        fat_sector = 0;
719
        do     
719
        do
720
        {
720
        {
721
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
721
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
722
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
722
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
723
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
723
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
Line 726... Line 726...
726
                        return(free_cluster);
726
                        return(free_cluster);
727
                }
727
                }
Line 728... Line 728...
728
 
728
 
Line 729... Line 729...
729
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
729
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
730
 
730
 
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. 
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
                {
732
                {
733
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
733
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
734
                        {                              
734
                        {
735
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used 
735
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
736
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
736
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
737
                                {
737
                                {
738
                                        Fat16_Deinit();
738
                                        Fat16_Deinit();
739
                                        return(free_cluster);
739
                                        return(free_cluster);
740
                                }
740
                                }
741
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);                          
741
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
742
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
742
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
743
                        }
743
                        }
744
                }
744
                }
745
                fat_sector++;                                                                                                   // continue the search in next fat sector
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                                                                        
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));
747
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
Line 758... Line 758...
758
/****************************************************************************************************************************************************/
758
/****************************************************************************************************************************************************/
759
s16 fseek_(File_t *file, s32 offset, s16 origin)
759
s16 fseek_(File_t *file, s32 offset, s16 origin)
760
{
760
{
761
        s32             fposition       = 0;
761
        s32             fposition       = 0;
762
        s16     retvalue        = 1;
762
        s16     retvalue        = 1;
763
       
763
 
764
        if((!Partition.IsValid) || (file == NULL)) return(0);
764
        if((!Partition.IsValid) || (file == NULL)) return(0);
765
        switch(origin)
765
        switch(origin)
766
        {
766
        {
767
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
767
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
768
                        fposition = 0; 
768
                        fposition = 0;
769
                        break;
769
                        break;
770
                case SEEK_END:                          // Fileposition relative to the end of the file.
770
                case SEEK_END:                          // Fileposition relative to the end of the file.
771
                        fposition = (s32)file->Size;
771
                        fposition = (s32)file->Size;
772
                        break;
772
                        break;
773
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
773
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
Line 787... Line 787...
787
                file->Position                          = 0;
787
                file->Position                          = 0;
Line 788... Line 788...
788
 
788
 
789
                while(file->Position < fposition)       // repeat until the current position is less than target
789
                while(file->Position < fposition)       // repeat until the current position is less than target
790
                {
790
                {
791
                        file->Position++;                               // increment file position
791
                        file->Position++;                               // increment file position
792
                        file->ByteOfCurrSector++;               // next byte in current sector                                                                          
792
                        file->ByteOfCurrSector++;               // next byte in current sector
793
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)                                                                 
793
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
794
                        {
794
                        {
795
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
795
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
796
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
796
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
797
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
797
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
798
                                {
798
                                {
799
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
799
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
800
                                        {
800
                                        {
801
                                                file->SectorOfCurrCluster = 0;         
801
                                                file->SectorOfCurrCluster = 0;
802
                                        }
802
                                        }
803
                                        else // the last cluster was allready reached
803
                                        else // the last cluster was allready reached
804
                                        {
804
                                        {
805
                                                file->SectorOfCurrCluster--;                                                    // jump back to the ast sector in the last cluster
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
806
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
807
                                        }
807
                                        }
808
                                }
808
                                }
809
                        }      
809
                        }
810
                }      
810
                }
811
        }
811
        }
812
        if(file->Position == fposition) retvalue = 0;  
812
        if(file->Position == fposition) retvalue = 0;
813
        return(retvalue);
813
        return(retvalue);
Line 814... Line 814...
814
}
814
}
Line 820... Line 820...
820
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
820
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
821
/*                                                                                                                                                                                                                                                                              */
821
/*                                                                                                                                                                                                                                                                              */
822
/****************************************************************************************************************************************/
822
/****************************************************************************************************************************************/
823
u8 DeleteClusterChain(u16 StartCluster)
823
u8 DeleteClusterChain(u16 StartCluster)
824
{
824
{
825
        u16 cluster;                                                                                                           
825
        u16 cluster;
826
        u32 fat_byte_offset, sector, byte;
826
        u32 fat_byte_offset, sector, byte;
827
        Fat16Entry_t * fat;
827
        Fat16Entry_t * fat;
828
        u8 buffer[BYTES_PER_SECTOR];
828
        u8 buffer[BYTES_PER_SECTOR];
829
        u32 sector_in_buffer = 0;
829
        u32 sector_in_buffer = 0;
830
        u8 repeat = 0;
830
        u8 repeat = 0;
Line 836... Line 836...
836
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
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
837
        // calculate the sector that contains the current cluster within the fat
838
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
838
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
839
        // calculate byte offset of the current cluster within that fat sector
839
        // calculate byte offset of the current cluster within that fat sector
840
        byte = fat_byte_offset % BYTES_PER_SECTOR;
840
        byte = fat_byte_offset % BYTES_PER_SECTOR;
841
        do     
841
        do
842
        {
842
        {
843
                if(sector != sector_in_buffer)
843
                if(sector != sector_in_buffer)
844
                {
844
                {
845
                        // read this sector to buffer
845
                        // read this sector to buffer
846
                        sector_in_buffer = sector;
846
                        sector_in_buffer = sector;
847
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
847
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
848
                }              
848
                }
849
                // read the next cluster from cache
849
                // read the next cluster from cache
850
                fat = (Fat16Entry_t *)(&(buffer[byte]));
850
                fat = (Fat16Entry_t *)(&(buffer[byte]));
851
                cluster = fat->NextCluster;
851
                cluster = fat->NextCluster;
852
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
852
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
853
                else repeat = 0;
853
                else repeat = 0;
Line 860... Line 860...
860
                // calculate byte offset of the current cluster within that fat sector
860
                // calculate byte offset of the current cluster within that fat sector
861
                byte = fat_byte_offset % BYTES_PER_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
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)
863
                if((sector != sector_in_buffer) || !repeat)
864
                {       // write sector in buffer
864
                {       // write sector in buffer
865
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;     
865
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;
866
                }
866
                }
867
        }
867
        }
868
        while(repeat);
868
        while(repeat);
Line 869... Line 869...
869
 
869
 
Line 878... Line 878...
878
/*                                                                                                                                                                                                                                                                              */
878
/*                                                                                                                                                                                                                                                                              */
879
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
879
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
880
/****************************************************************************************************************************************/
880
/****************************************************************************************************************************************/
881
u16 AppendCluster(File_t *file)
881
u16 AppendCluster(File_t *file)
882
{
882
{
883
        u16 last_cluster, new_cluster = 0;                                                                                                             
883
        u16 last_cluster, new_cluster = 0;
884
        u32 fat_byte_offset, sector, byte;
884
        u32 fat_byte_offset, sector, byte;
885
        Fat16Entry_t * fat;
885
        Fat16Entry_t * fat;
886
       
886
 
887
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
887
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
Line 888... Line 888...
888
 
888
 
889
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
889
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
890
        if(new_cluster)
890
        if(new_cluster)
891
        {       // A free cluster was found and can be added to the end of the file. 
891
        {       // A free cluster was found and can be added to the end of the file.
892
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
892
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
893
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster 
893
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
894
                fat_byte_offset = ((u32)last_cluster)<<1;
894
                fat_byte_offset = ((u32)last_cluster)<<1;
895
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
895
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
Line 896... Line 896...
896
                byte = fat_byte_offset % BYTES_PER_SECTOR;
896
                byte = fat_byte_offset % BYTES_PER_SECTOR;
Line 900... Line 900...
900
                        file->SectorInCache = sector;                                           // update sector stored in buffer
900
                        file->SectorInCache = sector;                                           // update sector stored in buffer
901
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
901
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
902
                        {
902
                        {
903
                                Fat16_Deinit();
903
                                Fat16_Deinit();
904
                                return(0);
904
                                return(0);
905
                        }      
905
                        }
906
                }                                            
906
                }
907
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
907
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
908
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
908
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
909
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
909
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
910
                {
910
                {
911
                        Fat16_Deinit();
911
                        Fat16_Deinit();
Line 934... Line 934...
934
        u8              i = 0;
934
        u8              i = 0;
935
        u8      direntry_exist = 0;
935
        u8      direntry_exist = 0;
936
        DirEntry_t * dir;
936
        DirEntry_t * dir;
Line 937... Line 937...
937
 
937
 
938
        // if incomming pointers are useless return immediatly
938
        // if incomming pointers are useless return immediatly
Line 939... Line 939...
939
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
939
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
940
 
940
 
941
        // dir entries can be searched only in filesclusters that have 
941
        // dir entries can be searched only in filesclusters that have
942
        // a corresponding dir entry with adir-flag set in its attribute 
942
        // a corresponding dir entry with adir-flag set in its attribute
943
        // or direct within the root directory area
943
        // or direct within the root directory area
944
       
944
 
945
        file->FirstSectorOfFirstCluster = 0;
945
        file->FirstSectorOfFirstCluster = 0;
946
        // no current directory exist therefore assume searching in the root
946
        // no current directory exist therefore assume searching in the root
947
        if(file->DirectorySector == 0)
947
        if(file->DirectorySector == 0)
Line 952... Line 952...
952
        // within the root directory area we can read sectors sequentially until the end of this area
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))
953
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
954
        {
954
        {
955
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
955
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
956
        }
956
        }
957
        // within the data clusters we can read sectors sequentially only within the cluster  
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))
958
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
959
        {
959
        {
960
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
960
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
961
        }
961
        }
962
        else return (direntry_exist); // bad sector range for directory sector of the file
962
        else return (direntry_exist); // bad sector range for directory sector of the file
Line 977... Line 977...
977
                        case SLOT_DELETED:
977
                        case SLOT_DELETED:
978
                                // the directrory pointer of this file points to a deleted or not existen directory
978
                                // the directrory pointer of this file points to a deleted or not existen directory
979
                                // therefore no file or subdirectory can be created
979
                                // therefore no file or subdirectory can be created
980
                                return (direntry_exist);
980
                                return (direntry_exist);
981
                                break;
981
                                break;
982
                        default:        // and is a real directory 
982
                        default:        // and is a real directory
983
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
983
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
984
                                {       // current file is not a directory therefore no file or subdirectory can be created here
984
                                {       // current file is not a directory therefore no file or subdirectory can be created here
985
                                        return (direntry_exist);
985
                                        return (direntry_exist);
986
                                }
986
                                }
987
                                break;
987
                                break;
988
                }
988
                }
989
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
989
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
990
        }
990
        }
Line 991... Line 991...
991
 
991
 
992
        // update current file data area position to start of first cluster
992
        // update current file data area position to start of first cluster
993
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
993
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
994
        file->SectorOfCurrCluster               = 0;           
994
        file->SectorOfCurrCluster               = 0;
Line 995... Line 995...
995
        file->ByteOfCurrSector                  = 0;
995
        file->ByteOfCurrSector                  = 0;
996
 
996
 
997
        do // loop over all data clusters of the current directory entry
997
        do // loop over all data clusters of the current directory entry
998
        {      
998
        {
999
                dir_sector = 0; // reset sector counter within a new cluster
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
1000
                do // loop over all sectors of a cluster or all sectors of the root directory
1001
                {      
1001
                {
1002
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1002
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1003
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
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
1004
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1005
                        {
1005
                        {
1006
                                Fat16_Deinit();
1006
                                Fat16_Deinit();
1007
                                return(direntry_exist);
1007
                                return(direntry_exist);
1008
                        }
1008
                        }
1009
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1009
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1010
                        // search all directory entries within that sector
1010
                        // search all directory entries within that sector
Line 1023... Line 1023...
1023
                                                i = 0;
1023
                                                i = 0;
1024
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1024
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1025
                                                if (i < 10) break; // names does not match
1025
                                                if (i < 10) break; // names does not match
1026
                                                // if dirname and attribute have matched
1026
                                                // if dirname and attribute have matched
1027
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
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                                                        
1028
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
1029
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1029
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1030
                                                file->SectorOfCurrCluster = 0;
1030
                                                file->SectorOfCurrCluster = 0;
1031
                                                file->ByteOfCurrSector = 0;
1031
                                                file->ByteOfCurrSector = 0;
1032
                                                file->DirectorySector = curr_sector; // current sector
1032
                                                file->DirectorySector = curr_sector; // current sector
1033
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1033
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1034
                                                file->Size = dir[dir_entry].Size;      
1034
                                                file->Size = dir[dir_entry].Size;
1035
                                                direntry_exist = 1; // mark as found    
1035
                                                direntry_exist = 1; // mark as found
1036
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop        
1036
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1037
                                } // end of first byte of name check
1037
                                } // end of first byte of name check
1038
                        }
1038
                        }
1039
                        dir_sector++; // search next sector
1039
                        dir_sector++; // search next sector
1040
                // stop if we reached the end of the cluster or the end of the root dir
1040
                // stop if we reached the end of the cluster or the end of the root dir
1041
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1041
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
Line 1042... Line 1042...
1042
 
1042
 
1043
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
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))                                                                                  
1044
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1045
                {
1045
                {
1046
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1046
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1047
                }
1047
                }
1048
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
1048
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
Line 1063... Line 1063...
1063
        u32 dir_sector, max_dir_sector, curr_sector;
1063
        u32 dir_sector, max_dir_sector, curr_sector;
1064
        u16 dir_entry   = 0;
1064
        u16 dir_entry   = 0;
1065
        u16 subdircluster, dircluster = 0;
1065
        u16 subdircluster, dircluster = 0;
1066
        u16 end_of_directory_not_reached = 0;
1066
        u16 end_of_directory_not_reached = 0;
1067
        u8      i                       = 0;
1067
        u8      i                       = 0;
1068
        u8      retvalue        = 0;   
1068
        u8      retvalue        = 0;
1069
        DirEntry_t *dir;
1069
        DirEntry_t *dir;
Line 1070... Line 1070...
1070
 
1070
 
1071
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
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!
1072
        // It is not checked here that the dir entry that should be created is already existent!
1073
       
1073
 
1074
        // Dir entries can be created only in file-clusters that have 
1074
        // Dir entries can be created only in file-clusters that have
1075
        // the dir-flag set in its attribute or within the root directory
1075
        // the dir-flag set in its attribute or within the root directory
1076
       
1076
 
1077
        file->FirstSectorOfFirstCluster = 0;
1077
        file->FirstSectorOfFirstCluster = 0;
1078
        // no current directory exist therefore assume creating in the root
1078
        // no current directory exist therefore assume creating in the root
1079
        if(file->DirectorySector == 0)
1079
        if(file->DirectorySector == 0)
1080
        {
1080
        {
Line 1085... Line 1085...
1085
        // within the root directory area we can read sectors sequentially until the end of this area
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))
1086
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1087
        {
1087
        {
1088
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1088
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1089
        }
1089
        }
1090
        // within the data clusters we can read sectors sequentially only within the cluster  
1090
        // within the data clusters we can read sectors sequentially only within the cluster
1091
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1091
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1092
        {
1092
        {
1093
                max_dir_sector = Partition.SectorsPerCluster;
1093
                max_dir_sector = Partition.SectorsPerCluster;
1094
        }
1094
        }
1095
        else return (retvalue); // bad sector range for directory sector of the file 
1095
        else return (retvalue); // bad sector range for directory sector of the file
1096
        // if search area is not defined yet
1096
        // if search area is not defined yet
1097
        if(file->FirstSectorOfFirstCluster == 0)
1097
        if(file->FirstSectorOfFirstCluster == 0)
1098
        {
1098
        {
1099
            // check if the directory entry of current file is existent and has the dir-flag set
1099
            // check if the directory entry of current file is existent and has the dir-flag set
1100
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1100
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1101
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
1101
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1102
                {
1102
                {
1103
                        Fat16_Deinit();
1103
                        Fat16_Deinit();
1104
                        return(retvalue);
1104
                        return(retvalue);
1105
                }              
1105
                }
1106
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1106
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1107
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
1107
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
1108
                {
1108
                {
1109
                        case SLOT_EMPTY:
1109
                        case SLOT_EMPTY:
1110
                        case SLOT_DELETED:
1110
                        case SLOT_DELETED:
1111
                                return (retvalue);
1111
                                return (retvalue);
1112
                                break;
1112
                                break;
1113
                        default:        // and is a real directory 
1113
                        default:        // and is a real directory
1114
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
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
1115
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1116
                                        return (retvalue);
1116
                                        return (retvalue);
1117
                                }
1117
                                }
1118
                                break;
1118
                                break;
1119
                }
1119
                }
1120
                dircluster = dir[file->DirectoryIndex].StartCluster;
1120
                dircluster = dir[file->DirectoryIndex].StartCluster;
1121
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1121
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1122
        }
1122
        }
1123
               
1123
 
1124
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1124
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1125
        if(subdircluster)
1125
        if(subdircluster)
1126
        {
1126
        {
1127
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1127
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1128
                file->SectorOfCurrCluster               = 0;
1128
                file->SectorOfCurrCluster               = 0;
1129
                do // loop over all clusters of current directory
1129
                do // loop over all clusters of current directory
1130
                {      
1130
                {
1131
                        dir_sector = 0; // reset sector counter within a new cluster
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
1132
                        do // loop over all sectors of a cluster or all sectors of the root directory
1133
                        {
1133
                        {
1134
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number                                                                      
1134
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1135
                                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
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. 
1136
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1137
                                {
1137
                                {
1138
                                        Fat16_Deinit();
1138
                                        Fat16_Deinit();
1139
                                        return(retvalue);
1139
                                        return(retvalue);
1140
                                }              
1140
                                }
1141
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1141
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1142
                                // search all directory entries of a sector
1142
                                // search all directory entries of a sector
1143
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1143
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1144
                                {       // check if current direntry is available
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))
1145
                                        if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1146
                                        {       // a free direntry was found    
1146
                                        {       // a free direntry was found
1147
                                                for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
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.
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.
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
1150
                                                dir[dir_entry].DateTime         = FileDateTime(&SystemTime);                    // set date/time
1151
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1151
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
Line 1160... Line 1160...
1160
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1160
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1161
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1161
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1162
                                                file->Size                                              = 0;                                                        // new file has no size
1162
                                                file->Size                                              = 0;                                                        // new file has no size
1163
                                                file->DirectorySector                   = curr_sector;
1163
                                                file->DirectorySector                   = curr_sector;
1164
                                                file->DirectoryIndex                    = dir_entry;
1164
                                                file->DirectoryIndex                    = dir_entry;
1165
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area          
1165
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1166
                                                {      
1166
                                                {
1167
                                                        ClearCurrCluster(file); // fill cluster with zeros
1167
                                                        ClearCurrCluster(file); // fill cluster with zeros
1168
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
1168
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
1169
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. 
1169
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1170
                                                        {
1170
                                                        {
1171
                                                                Fat16_Deinit();
1171
                                                                Fat16_Deinit();
1172
                                                                return(retvalue);
1172
                                                                return(retvalue);
1173
                                                        }      
1173
                                                        }
1174
                                                        dir = (DirEntry_t *)file->Cache;
1174
                                                        dir = (DirEntry_t *)file->Cache;
1175
                                                        // create direntry "." to current dir
1175
                                                        // create direntry "." to current dir
1176
                                                        dir[0].Name[0] = 0x2E;
1176
                                                        dir[0].Name[0] = 0x2E;
1177
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1177
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1178
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
1178
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
Line 1185... Line 1185...
1185
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1185
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1186
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
1186
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
1187
                                                        dir[1].StartCluster = dircluster;
1187
                                                        dir[1].StartCluster = dircluster;
1188
                                                        dir[1].DateTime = 0;
1188
                                                        dir[1].DateTime = 0;
1189
                                                        dir[1].Size = 0;
1189
                                                        dir[1].Size = 0;
1190
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. 
1190
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1191
                                                        {
1191
                                                        {
1192
                                                                Fat16_Deinit();
1192
                                                                Fat16_Deinit();
1193
                                                                return(retvalue);
1193
                                                                return(retvalue);
1194
                                                        }              
1194
                                                        }
1195
                                                }      
1195
                                                }
1196
                                                retvalue = 1;
1196
                                                retvalue = 1;
1197
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop        
1197
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1198
                                        }
1198
                                        }
1199
                                }                      
1199
                                }
1200
                                dir_sector++; // search next sector
1200
                                dir_sector++; // search next sector
1201
                        // stop if we reached the end of the cluster or the end of the root dir
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));
1202
                        }while((dir_sector < max_dir_sector) && (!retvalue));
1203
                       
1203
 
1204
                        // if we are seaching in the data area and the file not found in this cluster so take next cluster.
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))                                                                                
1205
                        if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1206
                        {
1206
                        {
1207
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1207
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1208
                        }
1208
                        }
1209
                }while((end_of_directory_not_reached) && (!retvalue));
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.
1210
                // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
Line 1235... Line 1235...
1235
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1235
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
Line 1236... Line 1236...
1236
 
1236
 
1237
        // trace along the filepath
1237
        // trace along the filepath
1238
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1238
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1239
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1239
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1240
        file->DirectoryIndex = 0;
1240
        file->DirectoryIndex = 0;
1241
        // as long as the file was not found and the remaining path is not empty
1241
        // as long as the file was not found and the remaining path is not empty
1242
        while((*path != 0) && !file_exist)
1242
        while((*path != 0) && !file_exist)
1243
        {       // separate dirname and subpath from filepath string
1243
        {       // separate dirname and subpath from filepath string
1244
                subpath = SeperateDirName(path, dirname);
1244
                subpath = SeperateDirName(path, dirname);
1245
                if(subpath != NULL)
1245
                if(subpath != NULL)
1246
                {      
1246
                {
1247
                        if(*subpath == 0)        
1247
                        if(*subpath == 0)
1248
                        {       // empty subpath indicates last element of dir chain
1248
                        {       // empty subpath indicates last element of dir chain
1249
                                af = attribfilter;
1249
                                af = attribfilter;
1250
                                am = attribmask;
1250
                                am = attribmask;
1251
                        }
1251
                        }
Line 1256... Line 1256...
1256
                        }
1256
                        }
1257
                        if(!DirectoryEntryExist(dirname, af, am, file))
1257
                        if(!DirectoryEntryExist(dirname, af, am, file))
1258
                        {
1258
                        {
1259
                                return (file_exist); // subdirectory does not exist
1259
                                return (file_exist); // subdirectory does not exist
1260
                        }
1260
                        }
1261
                        else
1261
                        else
1262
                        {      
1262
                        {
1263
                                if (*subpath == 0)
1263
                                if (*subpath == 0)
1264
                                {
1264
                                {
1265
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1265
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1266
                                }
1266
                                }
1267
                        }
1267
                        }
Line 1280... Line 1280...
1280
/********************************************************************************************************************************************/
1280
/********************************************************************************************************************************************/
1281
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1281
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1282
/*                                                                                                                                                                                                                                                                                      */
1282
/*                                                                                                                                                                                                                                                                                      */
1283
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
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                                                              */
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                                                                                               */                                                                                                             
1285
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1286
/*                                                                                                                                                                                                                                                                                      */
1286
/*                                                                                                                                                                                                                                                                                      */
1287
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1287
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1288
/********************************************************************************************************************************************/
1288
/********************************************************************************************************************************************/
1289
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1289
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1290
{
1290
{
Line 1304... Line 1304...
1304
        while((*path != 0) && !file_created)
1304
        while((*path != 0) && !file_created)
1305
        {   // separate dirname and subpath from filepath string
1305
        {   // separate dirname and subpath from filepath string
1306
                subpath = SeperateDirName(path, dirname);
1306
                subpath = SeperateDirName(path, dirname);
1307
                if(subpath != NULL)
1307
                if(subpath != NULL)
1308
                {
1308
                {
1309
                        if(*subpath == 0)        
1309
                        if(*subpath == 0)
1310
                        {       // empty subpath indicates last element of dir chain
1310
                        {       // empty subpath indicates last element of dir chain
1311
                                af = ATTR_NONE;
1311
                                af = ATTR_NONE;
1312
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1312
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1313
                        }
1313
                        }
1314
                        else  // it must be a subdirectory and no volume label
1314
                        else  // it must be a subdirectory and no volume label
Line 1319... Line 1319...
1319
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1319
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1320
                        {  // try to create subdir or file
1320
                        {  // try to create subdir or file
1321
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1321
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1322
                                if(!CreateDirectoryEntry(dirname, af, file))
1322
                                if(!CreateDirectoryEntry(dirname, af, file))
1323
                                {       // could not be created
1323
                                {       // could not be created
1324
                                        return(file_created);  
1324
                                        return(file_created);
1325
                                }
1325
                                }
1326
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1326
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1327
                        }
1327
                        }
1328
                }
1328
                }
1329
                else // error seperating the subpath
1329
                else // error seperating the subpath
1330
                {
1330
                {
Line 1344... Line 1344...
1344
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1344
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1345
/*                                                                                                                                                                                                                                                                                      */
1345
/*                                                                                                                                                                                                                                                                                      */
1346
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1346
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1347
/********************************************************************************************************************************************/
1347
/********************************************************************************************************************************************/
1348
File_t * fopen_(const s8 *filename, const s8 mode)
1348
File_t * fopen_(const s8 *filename, const s8 mode)
1349
{                      
1349
{
1350
        File_t *file    = 0;
1350
        File_t *file    = 0;
1351
       
1351
 
1352
        if((!Partition.IsValid) || (filename == 0)) return(file);
1352
        if((!Partition.IsValid) || (filename == 0)) return(file);
Line 1353... Line 1353...
1353
 
1353
 
1354
        // Look for an unused filepointer in the file pointer list?
1354
        // Look for an unused filepointer in the file pointer list?
1355
        file = LockFilePointer();
1355
        file = LockFilePointer();
1356
        // if no unused file pointer was found return 0
1356
        // if no unused file pointer was found return 0
Line 1357... Line 1357...
1357
        if(file == NULL) return(file);
1357
        if(file == NULL) return(file);
1358
 
1358
 
1359
        // now we have found a free filepointer and claimed it
1359
        // now we have found a free filepointer and claimed it
1360
        // so let initiate its property values
1360
        // so let initiate its property values
1361
        file->FirstSectorOfFirstCluster = 0;            // Sectorpointer to the first sector of the first datacluster of the file. 
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.
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).
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).
1364
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
Line 1369... Line 1369...
1369
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1369
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1370
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1370
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1371
        file->Attribute                                 = 0;            // the attribute of the file opened.
1371
        file->Attribute                                 = 0;            // the attribute of the file opened.
Line 1372... Line 1372...
1372
 
1372
 
1373
        // check if a real file (no directory) to the given filename exist
1373
        // check if a real file (no directory) to the given filename exist
1374
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1374
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1375
        {  // file exist
1375
        {  // file exist
1376
                switch(mode)  // check mode
1376
                switch(mode)  // check mode
1377
                {
1377
                {
1378
                        case 'a':       // if mode is: append to file
1378
                        case 'a':       // if mode is: append to file
Line 1405... Line 1405...
1405
                                        file->Position = 0;
1405
                                        file->Position = 0;
1406
                                        fseek_(file, 0, SEEK_SET);
1406
                                        fseek_(file, 0, SEEK_SET);
1407
                                }
1407
                                }
1408
                                break;
1408
                                break;
1409
                        case 'r':       // if mode is: read from file
1409
                        case 'r':       // if mode is: read from file
1410
                                // goto end of file 
1410
                                // goto end of file
1411
                                fseek_(file, 0, SEEK_SET);
1411
                                fseek_(file, 0, SEEK_SET);
1412
                                break;
1412
                                break;
1413
                        default: // other modes are not supported
1413
                        default: // other modes are not supported
1414
                                fclose_(file);
1414
                                fclose_(file);
1415
                                file = NULL;
1415
                                file = NULL;
1416
                        break;
1416
                        break;
1417
                }
1417
                }
1418
                return(file);  
1418
                return(file);
1419
        }
1419
        }
1420
        else // file does not exist
1420
        else // file does not exist
1421
        {
1421
        {
1422
                switch(mode)  // check mode
1422
                switch(mode)  // check mode
1423
                {
1423
                {
Line 1432... Line 1432...
1432
                                break;
1432
                                break;
1433
                        case 'r': // else opened for 'r'
1433
                        case 'r': // else opened for 'r'
1434
                        default:  // of unsupported mode
1434
                        default:  // of unsupported mode
1435
                                fclose_(file);
1435
                                fclose_(file);
1436
                                file = NULL;
1436
                                file = NULL;
1437
                                break; 
1437
                                break;
1438
                }
1438
                }
1439
                return(file);                  
1439
                return(file);
1440
        }
1440
        }
1441
        // we should never come to this point
1441
        // we should never come to this point
1442
        fclose_(file);
1442
        fclose_(file);
1443
        file = NULL;
1443
        file = NULL;
1444
        return(file);
1444
        return(file);
Line 1451... Line 1451...
1451
/*                                                                                                                                                                                                                                                                                                      */
1451
/*                                                                                                                                                                                                                                                                                                      */
1452
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1452
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1453
/****************************************************************************************************************************************************/
1453
/****************************************************************************************************************************************************/
1454
s16     fflush_(File_t *file)
1454
s16     fflush_(File_t *file)
1455
{
1455
{
1456
        DirEntry_t *dir;       
1456
        DirEntry_t *dir;
1457
       
1457
 
1458
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1458
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1459
               
1459
 
1460
        switch(file->Mode)
1460
        switch(file->Mode)
1461
        {
1461
        {
1462
                case 'a':
1462
                case 'a':
1463
                case 'w':
1463
                case 'w':
1464
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?             
1464
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1465
                        {
1465
                        {
1466
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer 
1466
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1467
                                {
1467
                                {
1468
                                        Fat16_Deinit();
1468
                                        Fat16_Deinit();
1469
                                        return(EOF);   
1469
                                        return(EOF);
1470
                                }                                      
1470
                                }
1471
                        }
1471
                        }
1472
                        file->SectorInCache     = file->DirectorySector;
1472
                        file->SectorInCache     = file->DirectorySector;
1473
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1473
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1474
                        {
1474
                        {
1475
                                Fat16_Deinit();
1475
                                Fat16_Deinit();
1476
                                return(EOF);    
1476
                                return(EOF);
1477
                        }
1477
                        }
1478
                       
1478
 
1479
                        dir = (DirEntry_t *)file->Cache;
1479
                        dir = (DirEntry_t *)file->Cache;
1480
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1480
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1481
                        dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime);         // update date time
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
1482
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1483
                        {
1483
                        {
Line 1519... Line 1519...
1519
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
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
/*                                                                                                                                                                                                                                                                                      */
1520
/*                                                                                                                                                                                                                                                                                      */
1521
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1521
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1522
/********************************************************************************************************************************************/
1522
/********************************************************************************************************************************************/
1523
s16 fgetc_(File_t *file)
1523
s16 fgetc_(File_t *file)
1524
{      
1524
{
1525
        s16 c = EOF;
1525
        s16 c = EOF;
1526
        u32 curr_sector;
1526
        u32 curr_sector;
1527
       
1527
 
1528
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1528
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1529
        // if the end of the file is not reached, get the next character.
1529
        // if the end of the file is not reached, get the next character.
1530
        if((0 < file->Size) && ((file->Position+1) < file->Size) )                                                             
1530
        if((0 < file->Size) && ((file->Position+1) < file->Size) )
1531
        {
1531
        {
1532
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1532
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1533
                curr_sector += file->SectorOfCurrCluster;                      
1533
                curr_sector += file->SectorOfCurrCluster;
1534
       
1534
 
1535
                if(file->SectorInCache != curr_sector)
1535
                if(file->SectorInCache != curr_sector)
1536
                {
1536
                {
1537
                        file->SectorInCache = curr_sector;
1537
                        file->SectorInCache = curr_sector;
1538
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1538
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1539
                        {
1539
                        {
1540
                                Fat16_Deinit();
1540
                                Fat16_Deinit();
1541
                                return(c);
1541
                                return(c);
1542
                        }              
1542
                        }
1543
                }      
1543
                }
1544
                c = (s16) file->Cache[file->ByteOfCurrSector];
1544
                c = (s16) file->Cache[file->ByteOfCurrSector];
1545
                file->Position++;                                                                       // increment file position
1545
                file->Position++;                                                                       // increment file position
1546
                file->ByteOfCurrSector++;                                                       // goto next byte in sector             
1546
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1547
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1547
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1548
                {
1548
                {
1549
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1549
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1550
                        file->SectorOfCurrCluster++;                                    //      next sector
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.
1551
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1552
                        {
1552
                        {
1553
                               
1553
 
1554
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1554
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1555
                                {
1555
                                {
1556
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1556
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1557
                                }
1557
                                }
1558
                                else // the last cluster was allready reached
1558
                                else // the last cluster was allready reached
Line 1573... Line 1573...
1573
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1573
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1574
/*                                                                                                                                                                                                                                                                                      */
1574
/*                                                                                                                                                                                                                                                                                      */
1575
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1575
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1576
/********************************************************************************************************************************************/
1576
/********************************************************************************************************************************************/
1577
s16 fputc_(const s8 c, File_t *file)
1577
s16 fputc_(const s8 c, File_t *file)
1578
{      
1578
{
1579
        u32 curr_sector  = 0;
1579
        u32 curr_sector  = 0;
1580
       
1580
 
1581
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1581
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
Line 1582... Line 1582...
1582
 
1582
 
1583
        // If file position equals to file size, then the end of file has reached.
1583
        // If file position equals to file size, then the end of file has reached.
1584
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR 
1584
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1585
        // and a new cluster should be appended.
1585
        // and a new cluster should be appended.
1586
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1586
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1587
        {
1587
        {
1588
                if(!AppendCluster(file)) return(EOF);
1588
                if(!AppendCluster(file)) return(EOF);
Line 1595... Line 1595...
1595
                file->SectorInCache = curr_sector;
1595
                file->SectorInCache = curr_sector;
1596
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1596
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1597
                {
1597
                {
1598
                        Fat16_Deinit();
1598
                        Fat16_Deinit();
1599
                        return(EOF);
1599
                        return(EOF);
1600
                }                      
1600
                }
1601
        }
1601
        }
Line 1602... Line 1602...
1602
 
1602
 
1603
        file->Cache[file->ByteOfCurrSector] = (u8)c;                    // write databyte into the buffer. The byte will be written to the device at once
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.
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.
1605
        file->Position++;                                                                       // the actual positon within the file.
1605
        file->Position++;                                                                       // the actual positon within the file.
1606
        file->ByteOfCurrSector++;                                                       // goto next byte in sector 
1606
        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1607
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1607
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1608
        {       // save the sector to the sd-card
1608
        {       // save the sector to the sd-card
1609
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1609
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1610
                {
1610
                {
Line 1625... Line 1625...
1625
                                }
1625
                                }
1626
                        }
1626
                        }
1627
                        else // next cluster
1627
                        else // next cluster
1628
                        {
1628
                        {
1629
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1629
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1630
                        }                                              
1630
                        }
1631
                }
1631
                }
1632
        }
1632
        }
1633
        return(0);
1633
        return(0);
1634
}
1634
}
Line 1646... Line 1646...
1646
{
1646
{
1647
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1647
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1648
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
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.
1649
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1650
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1650
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1651
        s16 c; 
1651
        s16 c;
Line 1652... Line 1652...
1652
 
1652
 
Line 1653... Line 1653...
1653
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1653
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1654
 
1654
 
1655
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1655
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1656
       
1656
 
1657
        while((object_cnt < count) && success)
1657
        while((object_cnt < count) && success)
1658
        {
1658
        {
1659
                object_size = size;
1659
                object_size = size;
Line 1666... Line 1666...
1666
                                pbuff++;
1666
                                pbuff++;
1667
                                size--;
1667
                                size--;
1668
                        }
1668
                        }
1669
                        else // error or end of file reached
1669
                        else // error or end of file reached
1670
                        {
1670
                        {
1671
                                success = 0;   
1671
                                success = 0;
1672
                        }
1672
                        }
1673
                }
1673
                }
1674
                if(success) object_cnt++;
1674
                if(success) object_cnt++;
1675
        }              
1675
        }
1676
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1676
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1677
}
1677
}
Line 1678... Line 1678...
1678
 
1678
 
Line 1689... Line 1689...
1689
{
1689
{
1690
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1690
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1691
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
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.
1692
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1693
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1693
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1694
        s16 c; 
1694
        s16 c;
Line 1695... Line 1695...
1695
 
1695
 
Line 1696... Line 1696...
1696
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1696
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1697
 
1697
 
1698
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1698
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1699
       
1699
 
1700
        while((object_cnt < count) && success)
1700
        while((object_cnt < count) && success)
1701
        {
1701
        {
1702
                object_size = size;
1702
                object_size = size;
Line 1712... Line 1712...
1712
                        {
1712
                        {
1713
                                success = 0;
1713
                                success = 0;
1714
                        }
1714
                        }
1715
                }
1715
                }
1716
                if(success) object_cnt++;
1716
                if(success) object_cnt++;
1717
        }              
1717
        }
1718
       
1718
 
1719
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1719
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1720
}                                                                                                                                                                              
1720
}
Line 1721... Line 1721...
1721
 
1721
 
1722
 
1722
 
1723
/****************************************************************************************************************************************/
1723
/****************************************************************************************************************************************/
Line 1729... Line 1729...
1729
/****************************************************************************************************************************************/
1729
/****************************************************************************************************************************************/
1730
s16 fputs_(const s8 *string, File_t *file)
1730
s16 fputs_(const s8 *string, File_t *file)
1731
{
1731
{
1732
        u8 i=0;
1732
        u8 i=0;
1733
        s16 c = 0;
1733
        s16 c = 0;
1734
       
1734
 
1735
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
1735
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
Line 1736... Line 1736...
1736
 
1736
 
1737
        while((string[i] != 0)&& (c != EOF))
1737
        while((string[i] != 0)&& (c != EOF))
1738
        {
1738
        {
Line 1751... Line 1751...
1751
/****************************************************************************************************************************************/
1751
/****************************************************************************************************************************************/
1752
u8 * fgets_(s8 *string, s16 length, File_t *file)
1752
u8 * fgets_(s8 *string, s16 length, File_t *file)
1753
{
1753
{
1754
        u8 *pbuff;
1754
        u8 *pbuff;
1755
        s16 c = 0;
1755
        s16 c = 0;
1756
       
1756
 
1757
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length = 0)) return (0);
1757
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length = 0)) return (0);
1758
        pbuff = string;
1758
        pbuff = string;
1759
        while(length > 1)                                                       // read the count-1 characters from the file to the string.
1759
        while(length > 1)                                                       // read the length-1 characters from the file to the string.
1760
        {
1760
        {
1761
                c = fgetc_(file);                                               // read a character from the opened file.
1761
                c = fgetc_(file);                                               // read a character from the opened file.
1762
                switch(c)
1762
                switch(c)
1763
                {
1763
                {
1764
                        case 0x0A:
1764
                        case 0x0A:
1765
                                c = 0;                                                  // set string terminator
1765
                                c = 0;                                                  // set string terminator
1766
                                length = 1;                                             // stop loop
1766
                                length = 1;                                             // stop loop
1767
                                break;
1767
                                break;
1768
                       
1768
 
1769
                        case EOF:
1769
                        case EOF:
1770
                                c = 0;                                                  // set string terminator
1770
                                c = 0;                                                  // set string terminator
1771
                                length = 1;                                             // stop loop
1771
                                length = 1;                                             // stop loop
1772
                                break; 
1772
                                break;
1773
                }
1773
                }
1774
                *pbuff = (u8)c;                                                 // copy byte to string
1774
                *pbuff = (s8)c;                                                 // copy byte to string
1775
                length--;
1775
                length--;
1776
                pbuff++;
1776
                pbuff++;
1777
        }
1777
        }
1778
        return(string);
1778
        return(string);
1779
}
1779
}
Line 1801... Line 1801...
1801
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1801
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1802
/*                                                                                                                                                                                                                                                                              */
1802
/*                                                                                                                                                                                                                                                                              */
1803
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1803
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1804
/****************************************************************************************************************************************/
1804
/****************************************************************************************************************************************/
1805
u8 feof_(File_t *file)
1805
u8 feof_(File_t *file)
1806
{      
1806
{
1807
        if(((file->Position)+1) < (file->Size))
1807
        if(((file->Position)+1) < (file->Size))
1808
        {
1808
        {
1809
                return(0);
1809
                return(0);
1810
        }
1810
        }
1811
        else
1811
        else
1812
        {
1812
        {
1813
                return(1);     
1813
                return(1);
1814
        }
1814
        }
1815
}
1815
}