Subversion Repositories NaviCtrl

Rev

Rev 109 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 109 Rev 171
1
/*#######################################################################################*/
1
/*#######################################################################################*/
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
2
/* !!! THIS IS NOT FREE SOFTWARE !!!                                                     */
3
/*#######################################################################################*/
3
/*#######################################################################################*/
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5
// + Copyright (c) 2008 Ingo Busker, Holger Buss
5
// + Copyright (c) 2008 Ingo Busker, Holger Buss
6
// + Nur für den privaten Gebrauch
6
// + Nur für den privaten Gebrauch / NON-COMMERCIAL USE ONLY
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 oder Nutzung 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 the sources to other systems or using the software on other systems (except hardware from www.mikrokopter.de) is not allowed
44
//
44
//
45
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
45
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
46
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
48
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
49
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53
// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53
// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
54
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55
// +  POSSIBILITY OF SUCH DAMAGE.
55
// +  POSSIBILITY OF SUCH DAMAGE.
56
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
56
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
57
#include <stdio.h>
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"
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
//
93
// URL:                                 www.Mikro-Control.de
93
// URL:                                 www.Mikro-Control.de
94
// mailto:                              stephan.busker@mikro-control.de
94
// mailto:                              stephan.busker@mikro-control.de
95
//________________________________________________________________________________________________________________________________________
95
//________________________________________________________________________________________________________________________________________
96
 
96
 
97
/*
97
/*
98
FAT16 Drive Layout:
98
FAT16 Drive Layout:
99
Description                                             Offset
99
Description                                             Offset
100
Volume Boot Sector                                      Start of Partition
100
Volume Boot Sector                                      Start of Partition
101
Fat Tables                                                      Start + # of Reserved Sectors
101
Fat Tables                                                      Start + # of Reserved Sectors
102
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
102
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
103
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
103
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
104
*/
104
*/
105
 
105
 
106
 
106
 
107
/*
107
/*
108
________________________________________________________________________________________________________________________________________
108
________________________________________________________________________________________________________________________________________
109
 
109
 
110
        Structure of an partition entry
110
        Structure of an partition entry
111
________________________________________________________________________________________________________________________________________
111
________________________________________________________________________________________________________________________________________
112
 
112
 
113
        Partition Entry is 16 bytes long
113
        Partition Entry is 16 bytes long
114
*/
114
*/
115
typedef struct
115
typedef struct
116
{
116
{
117
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
117
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
118
        u8      BeginningHead;                          // Beginning of Partition - Head
118
        u8      BeginningHead;                          // Beginning of Partition - Head
119
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
119
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
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;
126
 
126
 
127
/*
127
/*
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]
131
Sector is 5 bits:  [5:0] at [5:0]
131
Sector is 5 bits:  [5:0] at [5:0]
132
*/
132
*/
133
 
133
 
134
// Partition Types:
134
// Partition Types:
135
#define PART_TYPE_UNKNOWN                       0x00
135
#define PART_TYPE_UNKNOWN                       0x00
136
#define PART_TYPE_FAT12                         0x01
136
#define PART_TYPE_FAT12                         0x01
137
#define PART_TYPE_XENIX                         0x02
137
#define PART_TYPE_XENIX                         0x02
138
#define PART_TYPE_FAT16_ST_32_MB        0x04
138
#define PART_TYPE_FAT16_ST_32_MB        0x04
139
#define PART_TYPE_EXTDOS                        0x05
139
#define PART_TYPE_EXTDOS                        0x05
140
#define PART_TYPE_FAT16_LT_32_MB        0x06
140
#define PART_TYPE_FAT16_LT_32_MB        0x06
141
#define PART_TYPE_NTFS                          0x07
141
#define PART_TYPE_NTFS                          0x07
142
#define PART_TYPE_FAT32                         0x0B
142
#define PART_TYPE_FAT32                         0x0B
143
#define PART_TYPE_FAT32LBA                      0x0C
143
#define PART_TYPE_FAT32LBA                      0x0C
144
#define PART_TYPE_FAT16LBA                      0x0E
144
#define PART_TYPE_FAT16LBA                      0x0E
145
#define PART_TYPE_EXTDOSLBA                     0x0F
145
#define PART_TYPE_EXTDOSLBA                     0x0F
146
#define PART_TYPE_EISA                          0x12
146
#define PART_TYPE_EISA                          0x12
147
#define PART_TYPE_ONTRACK                       0x33
147
#define PART_TYPE_ONTRACK                       0x33
148
#define PART_TYPE_NOVELL                        0x40
148
#define PART_TYPE_NOVELL                        0x40
149
#define PART_TYPE_DYNAMIC                       0x42
149
#define PART_TYPE_DYNAMIC                       0x42
150
#define PART_TYPE_PCIX                          0x4B
150
#define PART_TYPE_PCIX                          0x4B
151
#define PART_TYPE_LINUX_SWAP            0x82
151
#define PART_TYPE_LINUX_SWAP            0x82
152
#define PART_TYPE_LINUX_NATIVE          0x83
152
#define PART_TYPE_LINUX_NATIVE          0x83
153
#define PART_TYPE_LINUX_LVM                     0x8E
153
#define PART_TYPE_LINUX_LVM                     0x8E
154
#define PART_TYPE_PHOENIXSAVE           0xA0
154
#define PART_TYPE_PHOENIXSAVE           0xA0
155
#define PART_TYPE_FREEBSD                       0xA5
155
#define PART_TYPE_FREEBSD                       0xA5
156
#define PART_TYPE_OPENBSD                       0xA6
156
#define PART_TYPE_OPENBSD                       0xA6
157
#define PART_TYPE_NETNBSD                       0xA9
157
#define PART_TYPE_NETNBSD                       0xA9
158
#define PART_TYPE_CPM                           0xDB
158
#define PART_TYPE_CPM                           0xDB
159
#define PART_TYPE_DBFS                          0xE0
159
#define PART_TYPE_DBFS                          0xE0
160
#define PART_TYPE_BBT                           0xFF
160
#define PART_TYPE_BBT                           0xFF
161
 
161
 
162
 
162
 
163
/*
163
/*
164
________________________________________________________________________________________________________________________________________
164
________________________________________________________________________________________________________________________________________
165
 
165
 
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
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
 
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
201
        u16 MaxRootEntries;                     // Maximum Root Directory Entries
201
        u16 MaxRootEntries;                     // Maximum Root Directory Entries
202
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
202
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
203
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
203
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
204
        u16 SectorsPerFAT;                      // Sectors Per FAT
204
        u16 SectorsPerFAT;                      // Sectors Per FAT
205
        u16 SectorsPerTrack;            // Sectors Per Track
205
        u16 SectorsPerTrack;            // Sectors Per Track
206
        u16 NoHeads;                            // Number of Heads
206
        u16 NoHeads;                            // Number of Heads
207
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
207
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
208
        u32 NoSectors;                          // Number of Sectors in Partition
208
        u32 NoSectors;                          // Number of Sectors in Partition
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;
217
 
217
 
218
 
218
 
219
 
219
 
220
/*
220
/*
221
________________________________________________________________________________________________________________________________________
221
________________________________________________________________________________________________________________________________________
222
 
222
 
223
        Structure of an directory entry
223
        Structure of an directory entry
224
________________________________________________________________________________________________________________________________________
224
________________________________________________________________________________________________________________________________________
225
 
225
 
226
        Directory entry is 32 bytes.
226
        Directory entry is 32 bytes.
227
*/
227
*/
228
typedef struct
228
typedef struct
229
{
229
{
230
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
230
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
231
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
231
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
232
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
232
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
233
        u8      Reserved[10];                           // reserved bytes within the directory entry.
233
        u8      Reserved[10];                           // reserved bytes within the directory entry.
234
        u32 DateTime;                                   // date and time of last write access to the file or directory.
234
        u32 DateTime;                                   // date and time of last write access to the file or directory.
235
        u16 StartCluster;                               // first cluster of the file or directory.
235
        u16 StartCluster;                               // first cluster of the file or directory.
236
        u32 Size;                                               // size of the file or directory in bytes.
236
        u32 Size;                                               // size of the file or directory in bytes.
237
}  __attribute__((packed)) DirEntry_t;
237
}  __attribute__((packed)) DirEntry_t;
238
 
238
 
239
#define SLOT_EMPTY              0x00    // slot has never been used
239
#define SLOT_EMPTY              0x00    // slot has never been used
240
#define SLOT_E5                 0x05    // the real value is 0xe5
240
#define SLOT_E5                 0x05    // the real value is 0xe5
241
#define SLOT_DELETED            0xE5    // file in this slot deleted
241
#define SLOT_DELETED            0xE5    // file in this slot deleted
242
 
242
 
243
#define ATTR_NONE               0x00    // normal file
243
#define ATTR_NONE               0x00    // normal file
244
#define ATTR_READONLY           0x01    // file is readonly
244
#define ATTR_READONLY           0x01    // file is readonly
245
#define ATTR_HIDDEN                     0x02    // file is hidden
245
#define ATTR_HIDDEN                     0x02    // file is hidden
246
#define ATTR_SYSTEM                     0x04    // file is a system file
246
#define ATTR_SYSTEM                     0x04    // file is a system file
247
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
247
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
248
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
248
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
249
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
249
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
250
#define ATTR_ARCHIVE            0x20    // file is new or modified
250
#define ATTR_ARCHIVE            0x20    // file is new or modified
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
260
{
260
{
261
        u16  NextCluster;                               // the next cluster of the file.
261
        u16  NextCluster;                               // the next cluster of the file.
262
} __attribute__((packed)) Fat16Entry_t;
262
} __attribute__((packed)) Fat16Entry_t;
263
 
263
 
264
// secial fat entries
264
// secial fat entries
265
#define FAT16_CLUSTER_FREE                      0x0000
265
#define FAT16_CLUSTER_FREE                      0x0000
266
#define FAT16_CLUSTER_RESERVED          0x0001
266
#define FAT16_CLUSTER_RESERVED          0x0001
267
#define FAT16_CLUSTER_USED_MIN          0x0002
267
#define FAT16_CLUSTER_USED_MIN          0x0002
268
#define FAT16_CLUSTER_USED_MAX          0xFFEF
268
#define FAT16_CLUSTER_USED_MAX          0xFFEF
269
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
269
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
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
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
/*                                                                                                                                                                                                                                                                               */
279
/*****************************************************************************************************************************************/
279
/*****************************************************************************************************************************************/
280
 
280
 
281
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
281
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
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
286
 
286
 
287
#define FSTATE_UNUSED   0
287
#define FSTATE_UNUSED   0
288
#define FSTATE_USED             1
288
#define FSTATE_USED             1
289
 
289
 
290
typedef struct
290
typedef struct
291
{
291
{
292
        u8      IsValid;                                // 0 means invalid, else valid
292
        u8      IsValid;                                // 0 means invalid, else valid
293
        u8      SectorsPerCluster;              // how many sectors does a cluster contain?
293
        u8      SectorsPerCluster;              // how many sectors does a cluster contain?
294
        u8      FatCopies;                              // Numbers of copies of the FAT
294
        u8      FatCopies;                              // Numbers of copies of the FAT
295
        u16     MaxRootEntries;                 // Possible number of entries in the root directory.
295
        u16     MaxRootEntries;                 // Possible number of entries in the root directory.
296
        u16     SectorsPerFat;                  // how many sectors does a fat16 contain?
296
        u16     SectorsPerFat;                  // how many sectors does a fat16 contain?
297
        u32 FirstFatSector;                     // sector of the start of the fat
297
        u32 FirstFatSector;                     // sector of the start of the fat
298
        u32 FirstRootDirSector;         // sector of the rootdirectory
298
        u32 FirstRootDirSector;         // sector of the rootdirectory
299
        u32 FirstDataSector;            // sector of the first cluster containing data (cluster2).
299
        u32 FirstDataSector;            // sector of the first cluster containing data (cluster2).
300
        u32 LastDataSector;                     // the last data sector of the partition
300
        u32 LastDataSector;                     // the last data sector of the partition
301
} Partition_t;
301
} Partition_t;
302
 
302
 
303
Partition_t     Partition;                                      // Structure holds partition information
303
Partition_t     Partition;                                      // Structure holds partition information
304
 
304
 
305
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
305
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
306
 
306
 
307
 
307
 
308
/****************************************************************************************************************************************/
308
/****************************************************************************************************************************************/
309
/*      Function:               FileDateTime(DateTime_t *);                                                                                                                                                                                     */
309
/*      Function:               FileDateTime(DateTime_t *);                                                                                                                                                                                     */
310
/*                                                                                                                                                                                                                                                                              */
310
/*                                                                                                                                                                                                                                                                              */
311
/*      Description:    This function calculates the DOS date time from a pointer to a time structure.                                                                          */
311
/*      Description:    This function calculates the DOS date time from a pointer to a time structure.                                                                          */
312
/*                                                                                                                                                                                                                                                                              */
312
/*                                                                                                                                                                                                                                                                              */
313
/*      Returnvalue:    Returns the DOS date time.                                                                                                                                                                                      */
313
/*      Returnvalue:    Returns the DOS date time.                                                                                                                                                                                      */
314
/****************************************************************************************************************************************/
314
/****************************************************************************************************************************************/
315
 
315
 
316
u32 FileDateTime(DateTime_t * pTimeStruct)
316
u32 FileDateTime(DateTime_t * pTimeStruct)
317
{
317
{
318
        u32 datetime = 0;
318
        u32 datetime = 0;
319
        if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime;
319
        if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime;
320
 
320
 
321
        datetime |= (0x0000007FL & (u32)(pTimeStruct->Year - 1980))<<25; // set year
321
        datetime |= (0x0000007FL & (u32)(pTimeStruct->Year - 1980))<<25; // set year
322
        datetime |= (0x0000000FL & (u32)(pTimeStruct->Month))<<21; // set month
322
        datetime |= (0x0000000FL & (u32)(pTimeStruct->Month))<<21; // set month
323
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Day))<<16;
323
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Day))<<16;
324
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Hour))<<11;
324
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Hour))<<11;
325
        datetime |= (0x0000003FL & (u32)(pTimeStruct->Min))<<5;
325
        datetime |= (0x0000003FL & (u32)(pTimeStruct->Min))<<5;
326
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Sec/2));
326
        datetime |= (0x0000001FL & (u32)(pTimeStruct->Sec/2));
327
        return datetime;
327
        return datetime;
328
}
328
}
329
 
329
 
330
 
330
 
331
/****************************************************************************************************************************************/
331
/****************************************************************************************************************************************/
332
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
332
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
333
/*                                                                                                                                                                                                                                                                              */
333
/*                                                                                                                                                                                                                                                                              */
334
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
334
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
335
/*                                                                                                                                                                                                                                                                              */
335
/*                                                                                                                                                                                                                                                                              */
336
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
336
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
337
/****************************************************************************************************************************************/
337
/****************************************************************************************************************************************/
338
File_t * LockFilePointer(void)
338
File_t * LockFilePointer(void)
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);
352
}
352
}
353
 
353
 
354
/****************************************************************************************************************************************/
354
/****************************************************************************************************************************************/
355
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
355
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
356
/*                                                                                                                                                                                                                                                                              */
356
/*                                                                                                                                                                                                                                                                              */
357
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
357
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
358
/*                                                                                                                                                                                                                                                                              */
358
/*                                                                                                                                                                                                                                                                              */
359
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
359
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
360
/****************************************************************************************************************************************/
360
/****************************************************************************************************************************************/
361
u8 UnlockFilePointer(File_t * file)
361
u8 UnlockFilePointer(File_t * file)
362
{
362
{
363
        u8 cnt;
363
        u8 cnt;
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)
376
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
376
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
377
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
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
}
388
 
388
 
389
/****************************************************************************************************************************************/
389
/****************************************************************************************************************************************/
390
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
390
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
391
/*                                                                                                                                                                                                                                                                              */
391
/*                                                                                                                                                                                                                                                                              */
392
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
392
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
393
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
393
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
394
/*                                      The subpath is the pointer to the remaining substring if the filepath                                                                                           */
394
/*                                      The subpath is the pointer to the remaining substring if the filepath                                                                                           */
395
/*                                                                                                                                                                                                                                                                              */
395
/*                                                                                                                                                                                                                                                                              */
396
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
396
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
397
/****************************************************************************************************************************************/
397
/****************************************************************************************************************************************/
398
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
398
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
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;
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++;
415
        }
415
        }
416
 
416
 
417
        // clear dirname with spaces
417
        // clear dirname with spaces
418
        dirname[11] = 0; // terminate dirname
418
        dirname[11] = 0; // terminate dirname
419
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
419
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
420
        writepointer = 0;
420
        writepointer = 0;
421
        // start seperating the dirname from the filepath.
421
        // start seperating the dirname from the filepath.
422
        readpointer = 0;
422
        readpointer = 0;
423
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
423
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
424
        while( &filepath[readpointer] < subpath)
424
        while( &filepath[readpointer] < subpath)
425
        {
425
        {
426
                if(writepointer >= 11) return(NULL);            // dirname to long
426
                if(writepointer >= 11) return(NULL);            // dirname to long
427
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
427
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
428
                {
428
                {
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
}
452
 
452
 
453
 
453
 
454
/**************************************************************************************************************************************+*/
454
/**************************************************************************************************************************************+*/
455
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
455
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
456
/*                                                                                                                                                                                                                                                                              */
456
/*                                                                                                                                                                                                                                                                              */
457
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
457
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
458
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
458
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
459
/*                                                                                                                                                                                                                                                                              */
459
/*                                                                                                                                                                                                                                                                              */
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
}
468
 
468
 
469
/****************************************************************************************************************************************/
469
/****************************************************************************************************************************************/
470
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
470
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
471
/*                                                                                                                                                                                                                                                                              */
471
/*                                                                                                                                                                                                                                                                              */
472
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
472
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
473
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
473
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
474
/*                                                                                                                                                                                                                                                                              */
474
/*                                                                                                                                                                                                                                                                              */
475
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
475
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
476
/****************************************************************************************************************************************/
476
/****************************************************************************************************************************************/
477
u16     SectorToFat16Cluster(u32 sector)
477
u16     SectorToFat16Cluster(u32 sector)
478
{
478
{
479
        if(!Partition.IsValid) return 0;
479
        if(!Partition.IsValid) return 0;
480
        return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
480
        return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
481
}
481
}
482
 
482
 
483
 
483
 
484
/****************************************************************************************************************************************/
484
/****************************************************************************************************************************************/
485
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                            */
485
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                            */
486
/*                                                                                                                                                                                                                                                                              */
486
/*                                                                                                                                                                                                                                                                              */
487
/*      Description:    This function return the Fat 15 filesystem state                                                                                                                                                        */
487
/*      Description:    This function return the Fat 15 filesystem state                                                                                                                                                        */
488
/*                                                                                                                                                                                                                                                                              */
488
/*                                                                                                                                                                                                                                                                              */
489
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
489
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
490
/****************************************************************************************************************************************/
490
/****************************************************************************************************************************************/
491
u8 Fat16_IsValid(void)
491
u8 Fat16_IsValid(void)
492
{
492
{
493
        return(Partition.IsValid);
493
        return(Partition.IsValid);
494
}
494
}
495
 
495
 
496
 
496
 
497
/****************************************************************************************************************************************/
497
/****************************************************************************************************************************************/
498
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
498
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
499
/*                                                                                                                                                                                                                                                                              */
499
/*                                                                                                                                                                                                                                                                              */
500
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
500
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
501
/*                                                                                                                                                                                                                                                                              */
501
/*                                                                                                                                                                                                                                                                              */
502
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
502
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
503
/****************************************************************************************************************************************/
503
/****************************************************************************************************************************************/
504
u8 Fat16_Deinit(void)
504
u8 Fat16_Deinit(void)
505
{
505
{
506
        s16 returnvalue = 0;
506
        s16 returnvalue = 0;
507
        u8 cnt;
507
        u8 cnt;
508
        // declare the filepointers as unused.
508
        // declare the filepointers as unused.
509
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
509
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
510
        {
510
        {
511
                if(FilePointer[cnt].State == FSTATE_USED)
511
                if(FilePointer[cnt].State == FSTATE_USED)
512
                {
512
                {
513
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
513
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
514
                }
514
                }
515
 
515
 
516
        }
516
        }
517
        SDC_Deinit();                   // uninitialize interface to sd-card
517
        SDC_Deinit();                   // uninitialize interface to sd-card
518
        Partition.IsValid = 0;  // mark data in partition structure as invalid
518
        Partition.IsValid = 0;  // mark data in partition structure as invalid
519
        return(returnvalue);
519
        return(returnvalue);
520
}
520
}
521
 
521
 
522
/****************************************************************************************************************************************/
522
/****************************************************************************************************************************************/
523
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
523
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
524
/*                                                                                                                                                                                                                                                                          */
524
/*                                                                                                                                                                                                                                                                          */
525
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
525
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
526
/*                                      and stores the information in global variables.                                                                                                                                     */
526
/*                                      and stores the information in global variables.                                                                                                                                     */
527
/*                                                                                                                                                                                                                                                                          */
527
/*                                                                                                                                                                                                                                                                          */
528
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
528
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
529
/****************************************************************************************************************************************/
529
/****************************************************************************************************************************************/
530
u8 Fat16_Init(void)
530
u8 Fat16_Init(void)
531
{
531
{
532
    u8  cnt     = 0;
532
    u8  cnt     = 0;
533
        u32     partitionfirstsector;
533
        u32     partitionfirstsector;
534
        VBR_Entry_t *VBR;
534
        VBR_Entry_t *VBR;
535
        MBR_Entry_t *MBR;
535
        MBR_Entry_t *MBR;
536
        File_t *file;
536
        File_t *file;
537
        u8 result = 0;
537
        u8 result = 0;
538
 
538
 
539
        SerialPutString("\r\n FAT16 init...");
539
        SerialPutString("\r\n FAT16 init...");
540
        Partition.IsValid = 0;
540
        Partition.IsValid = 0;
541
 
541
 
542
        // declare the filepointers as unused.
542
        // declare the filepointers as unused.
543
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
543
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
544
        {
544
        {
545
                FilePointer[cnt].State = FSTATE_UNUSED;
545
                FilePointer[cnt].State = FSTATE_UNUSED;
546
        }
546
        }
547
        // set current file pinter to first position in list
547
        // set current file pinter to first position in list
548
        file = &FilePointer[0];
548
        file = &FilePointer[0];
549
 
549
 
550
        // try to initialise the sd-card.
550
        // try to initialise the sd-card.
551
        if(SD_SUCCESS != SDC_Init())
551
        if(SD_SUCCESS != SDC_Init())
552
        {
552
        {
553
                SerialPutString("SD-Card could not be initialized.");
553
                SerialPutString("SD-Card could not be initialized.");
554
                result = 1;
554
                result = 1;
555
                goto end;
555
                goto end;
556
        }
556
        }
557
 
557
 
558
        // SD-Card is initialized successfully
558
        // SD-Card is initialized successfully
559
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
559
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
560
        {
560
        {
561
                SerialPutString("Error reading the MBR.");
561
                SerialPutString("Error reading the MBR.");
562
                result = 2;
562
                result = 2;
563
                goto end;
563
                goto end;
564
        }
564
        }
565
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
565
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
566
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
566
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
567
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
567
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
568
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
568
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
569
        {
569
        {
570
                // get sector offset 1st partition
570
                // get sector offset 1st partition
571
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
571
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
572
                // Start of Partition is the Volume Boot Sector
572
                // Start of Partition is the Volume Boot Sector
573
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
573
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
574
                {
574
                {
575
                        SerialPutString("Error reading the VBR.");
575
                        SerialPutString("Error reading the VBR.");
576
                        result = 3;
576
                        result = 3;
577
                        goto end;
577
                        goto end;
578
                }
578
                }
579
        }
579
        }
580
        else  // maybe the medium has no partition assuming sector 0 is the vbr
580
        else  // maybe the medium has no partition assuming sector 0 is the vbr
581
        {
581
        {
582
                partitionfirstsector = 0;
582
                partitionfirstsector = 0;
583
        }
583
        }
584
 
584
 
585
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
585
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
586
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
586
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
587
        {
587
        {
588
                SerialPutString("VBR: Sector size not supported.");
588
                SerialPutString("VBR: Sector size not supported.");
589
                result = 4;
589
                result = 4;
590
                goto end;
590
                goto end;
591
        }
591
        }
592
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
592
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
593
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
593
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
594
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
594
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
595
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
595
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
596
 
596
 
597
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
597
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
598
        // Calculate the position of the FileAllocationTable:
598
        // Calculate the position of the FileAllocationTable:
599
        // Start + # of Reserved Sectors
599
        // Start + # of Reserved Sectors
600
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
600
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
601
        // Calculate the position of the Rootdirectory:
601
        // Calculate the position of the Rootdirectory:
602
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
602
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
603
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
603
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
604
        // Calculate the position of the first datacluster:
604
        // Calculate the position of the first datacluster:
605
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
605
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
606
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
606
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
607
        // Calculate the last data sector
607
        // Calculate the last data sector
608
        if(VBR->NoSectors == 0)
608
        if(VBR->NoSectors == 0)
609
        {
609
        {
610
                SerialPutString("VBR: Bad number of sectors.");
610
                SerialPutString("VBR: Bad number of sectors.");
611
                result = 5;
611
                result = 5;
612
                goto end;
612
                goto end;
613
        }
613
        }
614
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
614
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
615
        // check for FAT16 in VBR of first partition
615
        // check for FAT16 in VBR of first partition
616
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
616
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
617
        {
617
        {
618
                SerialPutString("VBR: Partition ist not FAT16 type.");
618
                SerialPutString("VBR: Partition ist not FAT16 type.");
619
                result = 6;
619
                result = 6;
620
                goto end;
620
                goto end;
621
        }
621
        }
622
        Partition.IsValid = 1; // mark data in partition structure as valid
622
        Partition.IsValid = 1; // mark data in partition structure as valid
623
        result = 0;
623
        result = 0;
624
        end:
624
        end:
625
        if(result != 0) Fat16_Deinit();
625
        if(result != 0) Fat16_Deinit();
626
        else SerialPutString("ok");
626
        else SerialPutString("ok");
627
        return(result);
627
        return(result);
628
}
628
}
629
 
629
 
630
 
630
 
631
 
631
 
632
/****************************************************************************************************************************************/
632
/****************************************************************************************************************************************/
633
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
633
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
634
/*                                                                                                                                                                                                                                                                              */
634
/*                                                                                                                                                                                                                                                                              */
635
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
635
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
636
/*                                                                                                                                                                                                                                                                              */
636
/*                                                                                                                                                                                                                                                                              */
637
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
637
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
638
/****************************************************************************************************************************************/
638
/****************************************************************************************************************************************/
639
u8 ClearCurrCluster(File_t * file)
639
u8 ClearCurrCluster(File_t * file)
640
{
640
{
641
        u8 retvalue = 1;
641
        u8 retvalue = 1;
642
        u32 i;
642
        u32 i;
643
 
643
 
644
        if((!Partition.IsValid) || (file == NULL)) return(0);
644
        if((!Partition.IsValid) || (file == NULL)) return(0);
645
 
645
 
646
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
646
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
647
        for(i = 0; i < Partition.SectorsPerCluster; i++)
647
        for(i = 0; i < Partition.SectorsPerCluster; i++)
648
        {
648
        {
649
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
649
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
650
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
650
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
651
                {
651
                {
652
                        Fat16_Deinit();
652
                        Fat16_Deinit();
653
                        retvalue = 0;
653
                        retvalue = 0;
654
                }
654
                }
655
        }
655
        }
656
        return(retvalue);
656
        return(retvalue);
657
}
657
}
658
 
658
 
659
/*****************************************************************************************************************************************/
659
/*****************************************************************************************************************************************/
660
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
660
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
661
/*                                                                                                                                                                                                                                                                               */
661
/*                                                                                                                                                                                                                                                                               */
662
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
662
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
663
/*                                                                                                                                                                                                                                                                               */
663
/*                                                                                                                                                                                                                                                                               */
664
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
664
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
665
/*****************************************************************************************************************************************/
665
/*****************************************************************************************************************************************/
666
u16 GetNextCluster(File_t * file)
666
u16 GetNextCluster(File_t * file)
667
{
667
{
668
        u16 cluster = 0;
668
        u16 cluster = 0;
669
        u32 fat_byte_offset, sector, byte;
669
        u32 fat_byte_offset, sector, byte;
670
        Fat16Entry_t * fat;
670
        Fat16Entry_t * fat;
671
 
671
 
672
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
672
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
673
        // if sector is within the data area
673
        // if sector is within the data area
674
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
674
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
675
        {
675
        {
676
                // determine current file cluster
676
                // determine current file cluster
677
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
677
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
678
                // calculate byte offset in the fat for corresponding entry
678
                // calculate byte offset in the fat for corresponding entry
679
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
679
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
680
                // calculate the sector that contains the current cluster within the fat
680
                // calculate the sector that contains the current cluster within the fat
681
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
681
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
682
                // calculate byte offset of the current cluster within that fat sector
682
                // calculate byte offset of the current cluster within that fat sector
683
                byte = fat_byte_offset % BYTES_PER_SECTOR;
683
                byte = fat_byte_offset % BYTES_PER_SECTOR;
684
                // read this sector to the file cache
684
                // read this sector to the file cache
685
                if(file->SectorInCache != sector)
685
                if(file->SectorInCache != sector)
686
                {
686
                {
687
                        file->SectorInCache = sector;                                           // update sector stored in buffer
687
                        file->SectorInCache = sector;                                           // update sector stored in buffer
688
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
688
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
689
                        {
689
                        {
690
                                Fat16_Deinit();
690
                                Fat16_Deinit();
691
                                return (cluster);
691
                                return (cluster);
692
                        }
692
                        }
693
                }
693
                }
694
                // read the next cluster from cache
694
                // read the next cluster from cache
695
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
695
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
696
                cluster = fat->NextCluster;
696
                cluster = fat->NextCluster;
697
                // if last cluster fat entry
697
                // if last cluster fat entry
698
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
698
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
699
                {
699
                {
700
                         cluster = 0;
700
                         cluster = 0;
701
                }
701
                }
702
                else
702
                else
703
                {
703
                {
704
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
704
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
705
                        file->SectorOfCurrCluster = 0;
705
                        file->SectorOfCurrCluster = 0;
706
                        file->ByteOfCurrSector = 0;
706
                        file->ByteOfCurrSector = 0;
707
                }
707
                }
708
        }
708
        }
709
        return(cluster);
709
        return(cluster);
710
}
710
}
711
 
711
 
712
 
712
 
713
/****************************************************************************************************************************************/
713
/****************************************************************************************************************************************/
714
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
714
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
715
/*                                                                                                                                                                                                                                                                              */
715
/*                                                                                                                                                                                                                                                                              */
716
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
716
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
717
/*                                                                                                                                                                                                                                                                              */
717
/*                                                                                                                                                                                                                                                                              */
718
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
718
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
719
/****************************************************************************************************************************************/
719
/****************************************************************************************************************************************/
720
u16 FindNextFreeCluster(File_t *file)
720
u16 FindNextFreeCluster(File_t *file)
721
{
721
{
722
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
722
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
723
        u32     curr_sector;                            // current sector
723
        u32     curr_sector;                            // current sector
724
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
724
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
725
        u16     free_cluster    = 0;            // next free cluster number.
725
        u16     free_cluster    = 0;            // next free cluster number.
726
        Fat16Entry_t * fat;
726
        Fat16Entry_t * fat;
727
 
727
 
728
        if((!Partition.IsValid) || (file == NULL)) return(0);
728
        if((!Partition.IsValid) || (file == NULL)) return(0);
729
 
729
 
730
        // start searching for an empty cluster at the beginning of the fat.
730
        // start searching for an empty cluster at the beginning of the fat.
731
        fat_sector = 0;
731
        fat_sector = 0;
732
        do
732
        do
733
        {
733
        {
734
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
734
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
735
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
735
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
736
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
736
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
737
                {
737
                {
738
                        Fat16_Deinit();
738
                        Fat16_Deinit();
739
                        return(free_cluster);
739
                        return(free_cluster);
740
                }
740
                }
741
 
741
 
742
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
742
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
743
 
743
 
744
                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.
744
                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.
745
                {
745
                {
746
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
746
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
747
                        {
747
                        {
748
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
748
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
749
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
749
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
750
                                {
750
                                {
751
                                        Fat16_Deinit();
751
                                        Fat16_Deinit();
752
                                        return(free_cluster);
752
                                        return(free_cluster);
753
                                }
753
                                }
754
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
754
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
755
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
755
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
756
                        }
756
                        }
757
                }
757
                }
758
                fat_sector++;                                                                                                   // continue the search in next fat sector
758
                fat_sector++;                                                                                                   // continue the search in next fat sector
759
        // repeat until the end of the fat is  reached and no free cluster has been found so far
759
        // repeat until the end of the fat is  reached and no free cluster has been found so far
760
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
760
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
761
        return(free_cluster);
761
        return(free_cluster);
762
}
762
}
763
 
763
 
764
 
764
 
765
/****************************************************************************************************************************************************/
765
/****************************************************************************************************************************************************/
766
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
766
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
767
/*                                                                                                                                                                                                                                                                                                      */
767
/*                                                                                                                                                                                                                                                                                                      */
768
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
768
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
769
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
769
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
770
/* Returnvalue: Is 1 if seek was successful                                                                                                                                                                                                                                                                     */
770
/* Returnvalue: Is 1 if seek was successful                                                                                                                                                                                                                                                                     */
771
/****************************************************************************************************************************************************/
771
/****************************************************************************************************************************************************/
772
s16 fseek_(File_t *file, s32 offset, s16 origin)
772
s16 fseek_(File_t *file, s32 offset, s16 origin)
773
{
773
{
774
        s32             fposition       = 0;
774
        s32             fposition       = 0;
775
        s16     retvalue        = 1;
775
        s16     retvalue        = 1;
776
 
776
 
777
        if((!Partition.IsValid) || (file == NULL)) return(0);
777
        if((!Partition.IsValid) || (file == NULL)) return(0);
778
        switch(origin)
778
        switch(origin)
779
        {
779
        {
780
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
780
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
781
                        fposition = 0;
781
                        fposition = 0;
782
                        break;
782
                        break;
783
                case SEEK_END:                          // Fileposition relative to the end of the file.
783
                case SEEK_END:                          // Fileposition relative to the end of the file.
784
                        fposition = (s32)file->Size;
784
                        fposition = (s32)file->Size;
785
                        break;
785
                        break;
786
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
786
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
787
                default:
787
                default:
788
                        fposition = file->Position;
788
                        fposition = file->Position;
789
                        break;
789
                        break;
790
        }
790
        }
791
 
791
 
792
        fposition += offset;
792
        fposition += offset;
793
 
793
 
794
        if((fposition >= 0) && (fposition <= (s32)file->Size))          // is the pointer still within the file?
794
        if((fposition >= 0) && (fposition <= (s32)file->Size))          // is the pointer still within the file?
795
        {
795
        {
796
                // reset file position to start of the file
796
                // reset file position to start of the file
797
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
797
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
798
                file->SectorOfCurrCluster       = 0;
798
                file->SectorOfCurrCluster       = 0;
799
                file->ByteOfCurrSector          = 0;
799
                file->ByteOfCurrSector          = 0;
800
                file->Position                          = 0;
800
                file->Position                          = 0;
801
 
801
 
802
                while(file->Position < fposition)       // repeat until the current position is less than target
802
                while(file->Position < fposition)       // repeat until the current position is less than target
803
                {
803
                {
804
                        file->Position++;                               // increment file position
804
                        file->Position++;                               // increment file position
805
                        file->ByteOfCurrSector++;               // next byte in current sector
805
                        file->ByteOfCurrSector++;               // next byte in current sector
806
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
806
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
807
                        {
807
                        {
808
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
808
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
809
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
809
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
810
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
810
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
811
                                {
811
                                {
812
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
812
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
813
                                        {
813
                                        {
814
                                                file->SectorOfCurrCluster = 0;
814
                                                file->SectorOfCurrCluster = 0;
815
                                        }
815
                                        }
816
                                        else // the last cluster was allready reached
816
                                        else // the last cluster was allready reached
817
                                        {
817
                                        {
818
                                                file->SectorOfCurrCluster--;                                                    // jump back to the ast sector in the last cluster
818
                                                file->SectorOfCurrCluster--;                                                    // jump back to the ast sector in the last cluster
819
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
819
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
820
                                        }
820
                                        }
821
                                }
821
                                }
822
                        }
822
                        }
823
                }
823
                }
824
        }
824
        }
825
        if(file->Position == fposition) retvalue = 0;
825
        if(file->Position == fposition) retvalue = 0;
826
        return(retvalue);
826
        return(retvalue);
827
}
827
}
828
 
828
 
829
 
829
 
830
/****************************************************************************************************************************************/
830
/****************************************************************************************************************************************/
831
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
831
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
832
/*                                                                                                                                                                                                                                                                              */
832
/*                                                                                                                                                                                                                                                                              */
833
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
833
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
834
/*                                                                                                                                                                                                                                                                              */
834
/*                                                                                                                                                                                                                                                                              */
835
/****************************************************************************************************************************************/
835
/****************************************************************************************************************************************/
836
u8 DeleteClusterChain(u16 StartCluster)
836
u8 DeleteClusterChain(u16 StartCluster)
837
{
837
{
838
        u16 cluster;
838
        u16 cluster;
839
        u32 fat_byte_offset, sector, byte;
839
        u32 fat_byte_offset, sector, byte;
840
        Fat16Entry_t * fat;
840
        Fat16Entry_t * fat;
841
        u8 buffer[BYTES_PER_SECTOR];
841
        u8 buffer[BYTES_PER_SECTOR];
842
        u32 sector_in_buffer = 0;
842
        u32 sector_in_buffer = 0;
843
        u8 repeat = 0;
843
        u8 repeat = 0;
844
 
844
 
845
        if(!Partition.IsValid) return 0;
845
        if(!Partition.IsValid) return 0;
846
 
846
 
847
        cluster = StartCluster; // init chain trace
847
        cluster = StartCluster; // init chain trace
848
        // calculate byte offset in the fat for corresponding entry
848
        // calculate byte offset in the fat for corresponding entry
849
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
849
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
850
        // calculate the sector that contains the current cluster within the fat
850
        // calculate the sector that contains the current cluster within the fat
851
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
851
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
852
        // calculate byte offset of the current cluster within that fat sector
852
        // calculate byte offset of the current cluster within that fat sector
853
        byte = fat_byte_offset % BYTES_PER_SECTOR;
853
        byte = fat_byte_offset % BYTES_PER_SECTOR;
854
        do
854
        do
855
        {
855
        {
856
                if(sector != sector_in_buffer)
856
                if(sector != sector_in_buffer)
857
                {
857
                {
858
                        // read this sector to buffer
858
                        // read this sector to buffer
859
                        sector_in_buffer = sector;
859
                        sector_in_buffer = sector;
860
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
860
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
861
                }
861
                }
862
                // read the next cluster from cache
862
                // read the next cluster from cache
863
                fat = (Fat16Entry_t *)(&(buffer[byte]));
863
                fat = (Fat16Entry_t *)(&(buffer[byte]));
864
                cluster = fat->NextCluster;
864
                cluster = fat->NextCluster;
865
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
865
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
866
                else repeat = 0;
866
                else repeat = 0;
867
 
867
 
868
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
868
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
869
                // calculate byte offset in the fat for corresponding entry
869
                // calculate byte offset in the fat for corresponding entry
870
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
870
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
871
                // calculate the sector that contains the current cluster within the fat
871
                // calculate the sector that contains the current cluster within the fat
872
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
872
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
873
                // calculate byte offset of the current cluster within that fat sector
873
                // calculate byte offset of the current cluster within that fat sector
874
                byte = fat_byte_offset % BYTES_PER_SECTOR;
874
                byte = fat_byte_offset % BYTES_PER_SECTOR;
875
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
875
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
876
                if((sector != sector_in_buffer) || !repeat)
876
                if((sector != sector_in_buffer) || !repeat)
877
                {       // write sector in buffer
877
                {       // write sector in buffer
878
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;
878
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;
879
                }
879
                }
880
        }
880
        }
881
        while(repeat);
881
        while(repeat);
882
 
882
 
883
        return 1;
883
        return 1;
884
}
884
}
885
 
885
 
886
 
886
 
887
/****************************************************************************************************************************************/
887
/****************************************************************************************************************************************/
888
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
888
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
889
/*                                                                                                                                                                                                                                                                              */
889
/*                                                                                                                                                                                                                                                                              */
890
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
890
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
891
/*                                                                                                                                                                                                                                                                              */
891
/*                                                                                                                                                                                                                                                                              */
892
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
892
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
893
/****************************************************************************************************************************************/
893
/****************************************************************************************************************************************/
894
u16 AppendCluster(File_t *file)
894
u16 AppendCluster(File_t *file)
895
{
895
{
896
        u16 last_cluster, new_cluster = 0;
896
        u16 last_cluster, new_cluster = 0;
897
        u32 fat_byte_offset, sector, byte;
897
        u32 fat_byte_offset, sector, byte;
898
        Fat16Entry_t * fat;
898
        Fat16Entry_t * fat;
899
 
899
 
900
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
900
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
901
 
901
 
902
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
902
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
903
        if(new_cluster)
903
        if(new_cluster)
904
        {       // A free cluster was found and can be added to the end of the file.
904
        {       // A free cluster was found and can be added to the end of the file.
905
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
905
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
906
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
906
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
907
                fat_byte_offset = ((u32)last_cluster)<<1;
907
                fat_byte_offset = ((u32)last_cluster)<<1;
908
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
908
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
909
                byte = fat_byte_offset % BYTES_PER_SECTOR;
909
                byte = fat_byte_offset % BYTES_PER_SECTOR;
910
 
910
 
911
                if(file->SectorInCache != sector)
911
                if(file->SectorInCache != sector)
912
                {
912
                {
913
                        file->SectorInCache = sector;                                           // update sector stored in buffer
913
                        file->SectorInCache = sector;                                           // update sector stored in buffer
914
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
914
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
915
                        {
915
                        {
916
                                Fat16_Deinit();
916
                                Fat16_Deinit();
917
                                return(0);
917
                                return(0);
918
                        }
918
                        }
919
                }
919
                }
920
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
920
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
921
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
921
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
922
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
922
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
923
                {
923
                {
924
                        Fat16_Deinit();
924
                        Fat16_Deinit();
925
                        return(0);
925
                        return(0);
926
                }
926
                }
927
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
927
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
928
                file->SectorOfCurrCluster = 0;
928
                file->SectorOfCurrCluster = 0;
929
                file->ByteOfCurrSector = 0;
929
                file->ByteOfCurrSector = 0;
930
        }
930
        }
931
        return(new_cluster);
931
        return(new_cluster);
932
}
932
}
933
 
933
 
934
/****************************************************************************************************************************************************/
934
/****************************************************************************************************************************************************/
935
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
935
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
936
/*                                                                                                                                                                                                                                                                                                      */
936
/*                                                                                                                                                                                                                                                                                                      */
937
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
937
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
938
/*                                                                                                                                                                                                                                                                                                      */
938
/*                                                                                                                                                                                                                                                                                                      */
939
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
939
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
940
/****************************************************************************************************************************************************/
940
/****************************************************************************************************************************************************/
941
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
941
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
942
{
942
{
943
        u32             dir_sector, max_dir_sector, curr_sector;
943
        u32             dir_sector, max_dir_sector, curr_sector;
944
        u16     dir_entry = 0;
944
        u16     dir_entry = 0;
945
 
945
 
946
        u16     end_of_directory_not_reached = 0;
946
        u16     end_of_directory_not_reached = 0;
947
        u8              i = 0;
947
        u8              i = 0;
948
        u8      direntry_exist = 0;
948
        u8      direntry_exist = 0;
949
        DirEntry_t * dir;
949
        DirEntry_t * dir;
950
 
950
 
951
        // if incomming pointers are useless return immediatly
951
        // if incomming pointers are useless return immediatly
952
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
952
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
953
 
953
 
954
        // dir entries can be searched only in filesclusters that have
954
        // dir entries can be searched only in filesclusters that have
955
        // a corresponding dir entry with adir-flag set in its attribute
955
        // a corresponding dir entry with adir-flag set in its attribute
956
        // or direct within the root directory area
956
        // or direct within the root directory area
957
 
957
 
958
        file->FirstSectorOfFirstCluster = 0;
958
        file->FirstSectorOfFirstCluster = 0;
959
        // no current directory exist therefore assume searching in the root
959
        // no current directory exist therefore assume searching in the root
960
        if(file->DirectorySector == 0)
960
        if(file->DirectorySector == 0)
961
        {
961
        {
962
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
962
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
963
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
963
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
964
        }
964
        }
965
        // within the root directory area we can read sectors sequentially until the end of this area
965
        // within the root directory area we can read sectors sequentially until the end of this area
966
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
966
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
967
        {
967
        {
968
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
968
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
969
        }
969
        }
970
        // within the data clusters we can read sectors sequentially only within the cluster
970
        // within the data clusters we can read sectors sequentially only within the cluster
971
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
971
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
972
        {
972
        {
973
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
973
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
974
        }
974
        }
975
        else return (direntry_exist); // bad sector range for directory sector of the file
975
        else return (direntry_exist); // bad sector range for directory sector of the file
976
        // if search area is not defined yet
976
        // if search area is not defined yet
977
        if(file->FirstSectorOfFirstCluster == 0)
977
        if(file->FirstSectorOfFirstCluster == 0)
978
        {
978
        {
979
                // check if the directory entry of current file is existent and has the dir-flag set
979
                // check if the directory entry of current file is existent and has the dir-flag set
980
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
980
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
981
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
981
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
982
                {
982
                {
983
                        Fat16_Deinit();
983
                        Fat16_Deinit();
984
                        return(direntry_exist);
984
                        return(direntry_exist);
985
                }
985
                }
986
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
986
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
987
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
987
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
988
                {
988
                {
989
                        case SLOT_EMPTY:
989
                        case SLOT_EMPTY:
990
                        case SLOT_DELETED:
990
                        case SLOT_DELETED:
991
                                // the directrory pointer of this file points to a deleted or not existen directory
991
                                // the directrory pointer of this file points to a deleted or not existen directory
992
                                // therefore no file or subdirectory can be created
992
                                // therefore no file or subdirectory can be created
993
                                return (direntry_exist);
993
                                return (direntry_exist);
994
                                break;
994
                                break;
995
                        default:        // and is a real directory
995
                        default:        // and is a real directory
996
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
996
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
997
                                {       // current file is not a directory therefore no file or subdirectory can be created here
997
                                {       // current file is not a directory therefore no file or subdirectory can be created here
998
                                        return (direntry_exist);
998
                                        return (direntry_exist);
999
                                }
999
                                }
1000
                                break;
1000
                                break;
1001
                }
1001
                }
1002
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
1002
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
1003
        }
1003
        }
1004
 
1004
 
1005
        // update current file data area position to start of first cluster
1005
        // update current file data area position to start of first cluster
1006
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1006
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1007
        file->SectorOfCurrCluster               = 0;
1007
        file->SectorOfCurrCluster               = 0;
1008
        file->ByteOfCurrSector                  = 0;
1008
        file->ByteOfCurrSector                  = 0;
1009
 
1009
 
1010
        do // loop over all data clusters of the current directory entry
1010
        do // loop over all data clusters of the current directory entry
1011
        {
1011
        {
1012
                dir_sector = 0; // reset sector counter within a new cluster
1012
                dir_sector = 0; // reset sector counter within a new cluster
1013
                do // loop over all sectors of a cluster or all sectors of the root directory
1013
                do // loop over all sectors of a cluster or all sectors of the root directory
1014
                {
1014
                {
1015
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1015
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1016
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1016
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1017
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1017
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1018
                        {
1018
                        {
1019
                                Fat16_Deinit();
1019
                                Fat16_Deinit();
1020
                                return(direntry_exist);
1020
                                return(direntry_exist);
1021
                        }
1021
                        }
1022
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1022
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1023
                        // search all directory entries within that sector
1023
                        // search all directory entries within that sector
1024
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1024
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1025
                        {   // check for existing dir entry
1025
                        {   // check for existing dir entry
1026
                                switch((u8)dir[dir_entry].Name[0])
1026
                                switch((u8)dir[dir_entry].Name[0])
1027
                                {
1027
                                {
1028
                                        case SLOT_EMPTY:
1028
                                        case SLOT_EMPTY:
1029
                                        case SLOT_DELETED:
1029
                                        case SLOT_DELETED:
1030
                                                // ignore empty or deleted dir entries
1030
                                                // ignore empty or deleted dir entries
1031
                                                break;
1031
                                                break;
1032
                                        default:
1032
                                        default:
1033
                                                // if existing check attributes before names are compared will safe performance
1033
                                                // if existing check attributes before names are compared will safe performance
1034
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1034
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1035
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
1035
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
1036
                                                i = 0;
1036
                                                i = 0;
1037
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1037
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1038
                                                if (i < 10) break; // names does not match
1038
                                                if (i < 10) break; // names does not match
1039
                                                // if dirname and attribute have matched
1039
                                                // if dirname and attribute have matched
1040
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
1040
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
1041
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
1041
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
1042
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1042
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1043
                                                file->SectorOfCurrCluster = 0;
1043
                                                file->SectorOfCurrCluster = 0;
1044
                                                file->ByteOfCurrSector = 0;
1044
                                                file->ByteOfCurrSector = 0;
1045
                                                file->DirectorySector = curr_sector; // current sector
1045
                                                file->DirectorySector = curr_sector; // current sector
1046
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1046
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1047
                                                file->Size = dir[dir_entry].Size;
1047
                                                file->Size = dir[dir_entry].Size;
1048
                                                direntry_exist = 1; // mark as found
1048
                                                direntry_exist = 1; // mark as found
1049
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1049
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1050
                                } // end of first byte of name check
1050
                                } // end of first byte of name check
1051
                        }
1051
                        }
1052
                        dir_sector++; // search next sector
1052
                        dir_sector++; // search next sector
1053
                // stop if we reached the end of the cluster or the end of the root dir
1053
                // stop if we reached the end of the cluster or the end of the root dir
1054
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1054
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1055
 
1055
 
1056
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1056
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1057
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1057
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1058
                {
1058
                {
1059
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1059
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1060
                }
1060
                }
1061
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
1061
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
1062
        return(direntry_exist);
1062
        return(direntry_exist);
1063
}
1063
}
1064
 
1064
 
1065
 
1065
 
1066
/****************************************************************************************************************************************/
1066
/****************************************************************************************************************************************/
1067
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1067
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1068
/*                                                                                                                                                                                                                                                                              */
1068
/*                                                                                                                                                                                                                                                                              */
1069
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
1069
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
1070
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
1070
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
1071
/*                                                                                                                                                                                                                                                                              */
1071
/*                                                                                                                                                                                                                                                                              */
1072
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1072
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1073
/****************************************************************************************************************************************/
1073
/****************************************************************************************************************************************/
1074
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1074
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1075
{
1075
{
1076
        u32 dir_sector, max_dir_sector, curr_sector;
1076
        u32 dir_sector, max_dir_sector, curr_sector;
1077
        u16 dir_entry   = 0;
1077
        u16 dir_entry   = 0;
1078
        u16 subdircluster, dircluster = 0;
1078
        u16 subdircluster, dircluster = 0;
1079
        u16 end_of_directory_not_reached = 0;
1079
        u16 end_of_directory_not_reached = 0;
1080
        u8      i                       = 0;
1080
        u8      i                       = 0;
1081
        u8      retvalue        = 0;
1081
        u8      retvalue        = 0;
1082
        DirEntry_t *dir;
1082
        DirEntry_t *dir;
1083
 
1083
 
1084
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
1084
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
1085
        // It is not checked here that the dir entry that should be created is already existent!
1085
        // It is not checked here that the dir entry that should be created is already existent!
1086
 
1086
 
1087
        // Dir entries can be created only in file-clusters that have
1087
        // Dir entries can be created only in file-clusters that have
1088
        // the dir-flag set in its attribute or within the root directory
1088
        // the dir-flag set in its attribute or within the root directory
1089
 
1089
 
1090
        file->FirstSectorOfFirstCluster = 0;
1090
        file->FirstSectorOfFirstCluster = 0;
1091
        // no current directory exist therefore assume creating in the root
1091
        // no current directory exist therefore assume creating in the root
1092
        if(file->DirectorySector == 0)
1092
        if(file->DirectorySector == 0)
1093
        {
1093
        {
1094
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1094
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1095
                dircluster = 0;
1095
                dircluster = 0;
1096
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1096
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1097
        }
1097
        }
1098
        // within the root directory area we can read sectors sequentially until the end of this area
1098
        // within the root directory area we can read sectors sequentially until the end of this area
1099
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1099
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1100
        {
1100
        {
1101
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1101
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1102
        }
1102
        }
1103
        // within the data clusters we can read sectors sequentially only within the cluster
1103
        // within the data clusters we can read sectors sequentially only within the cluster
1104
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1104
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1105
        {
1105
        {
1106
                max_dir_sector = Partition.SectorsPerCluster;
1106
                max_dir_sector = Partition.SectorsPerCluster;
1107
        }
1107
        }
1108
        else return (retvalue); // bad sector range for directory sector of the file
1108
        else return (retvalue); // bad sector range for directory sector of the file
1109
        // if search area is not defined yet
1109
        // if search area is not defined yet
1110
        if(file->FirstSectorOfFirstCluster == 0)
1110
        if(file->FirstSectorOfFirstCluster == 0)
1111
        {
1111
        {
1112
            // check if the directory entry of current file is existent and has the dir-flag set
1112
            // check if the directory entry of current file is existent and has the dir-flag set
1113
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1113
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1114
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1114
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1115
                {
1115
                {
1116
                        Fat16_Deinit();
1116
                        Fat16_Deinit();
1117
                        return(retvalue);
1117
                        return(retvalue);
1118
                }
1118
                }
1119
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1119
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1120
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
1120
                switch((u8)dir[file->DirectoryIndex].Name[0])                                   // check if current directory exist
1121
                {
1121
                {
1122
                        case SLOT_EMPTY:
1122
                        case SLOT_EMPTY:
1123
                        case SLOT_DELETED:
1123
                        case SLOT_DELETED:
1124
                                return (retvalue);
1124
                                return (retvalue);
1125
                                break;
1125
                                break;
1126
                        default:        // and is a real directory
1126
                        default:        // and is a real directory
1127
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1127
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1128
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1128
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1129
                                        return (retvalue);
1129
                                        return (retvalue);
1130
                                }
1130
                                }
1131
                                break;
1131
                                break;
1132
                }
1132
                }
1133
                dircluster = dir[file->DirectoryIndex].StartCluster;
1133
                dircluster = dir[file->DirectoryIndex].StartCluster;
1134
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1134
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1135
        }
1135
        }
1136
 
1136
 
1137
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1137
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1138
        if(subdircluster)
1138
        if(subdircluster)
1139
        {
1139
        {
1140
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1140
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1141
                file->SectorOfCurrCluster               = 0;
1141
                file->SectorOfCurrCluster               = 0;
1142
                do // loop over all clusters of current directory
1142
                do // loop over all clusters of current directory
1143
                {
1143
                {
1144
                        dir_sector = 0; // reset sector counter within a new cluster
1144
                        dir_sector = 0; // reset sector counter within a new cluster
1145
                        do // loop over all sectors of a cluster or all sectors of the root directory
1145
                        do // loop over all sectors of a cluster or all sectors of the root directory
1146
                        {
1146
                        {
1147
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1147
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1148
                                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1148
                                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1149
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1149
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1150
                                {
1150
                                {
1151
                                        Fat16_Deinit();
1151
                                        Fat16_Deinit();
1152
                                        return(retvalue);
1152
                                        return(retvalue);
1153
                                }
1153
                                }
1154
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1154
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1155
                                // search all directory entries of a sector
1155
                                // search all directory entries of a sector
1156
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1156
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1157
                                {       // check if current direntry is available
1157
                                {       // check if current direntry is available
1158
                                        if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1158
                                        if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1159
                                        {       // a free direntry was found
1159
                                        {       // a free direntry was found
1160
                                                for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1160
                                                for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1161
                                                dir[dir_entry].Attribute    = attrib;                                                           // Set the attribute of the new directoryentry.
1161
                                                dir[dir_entry].Attribute    = attrib;                                                           // Set the attribute of the new directoryentry.
1162
                                                dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1162
                                                dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1163
                                                dir[dir_entry].DateTime         = FileDateTime(&SystemTime);                    // set date/time
1163
                                                dir[dir_entry].DateTime         = FileDateTime(&SystemTime);                    // set date/time
1164
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1164
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1165
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1165
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1166
                                                {
1166
                                                {
1167
                                                        Fat16_Deinit();
1167
                                                        Fat16_Deinit();
1168
                                                        return(retvalue);
1168
                                                        return(retvalue);
1169
                                                }
1169
                                                }
1170
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1170
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1171
                                                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1171
                                                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1172
                                                file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1172
                                                file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1173
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1173
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1174
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1174
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1175
                                                file->Size                                              = 0;                                                        // new file has no size
1175
                                                file->Size                                              = 0;                                                        // new file has no size
1176
                                                file->DirectorySector                   = curr_sector;
1176
                                                file->DirectorySector                   = curr_sector;
1177
                                                file->DirectoryIndex                    = dir_entry;
1177
                                                file->DirectoryIndex                    = dir_entry;
1178
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1178
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1179
                                                {
1179
                                                {
1180
                                                        ClearCurrCluster(file); // fill cluster with zeros
1180
                                                        ClearCurrCluster(file); // fill cluster with zeros
1181
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
1181
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
1182
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1182
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1183
                                                        {
1183
                                                        {
1184
                                                                Fat16_Deinit();
1184
                                                                Fat16_Deinit();
1185
                                                                return(retvalue);
1185
                                                                return(retvalue);
1186
                                                        }
1186
                                                        }
1187
                                                        dir = (DirEntry_t *)file->Cache;
1187
                                                        dir = (DirEntry_t *)file->Cache;
1188
                                                        // create direntry "." to current dir
1188
                                                        // create direntry "." to current dir
1189
                                                        dir[0].Name[0] = 0x2E;
1189
                                                        dir[0].Name[0] = 0x2E;
1190
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1190
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1191
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
1191
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
1192
                                                        dir[0].StartCluster = subdircluster;
1192
                                                        dir[0].StartCluster = subdircluster;
1193
                                                        dir[0].DateTime = 0;
1193
                                                        dir[0].DateTime = 0;
1194
                                                        dir[0].Size = 0;
1194
                                                        dir[0].Size = 0;
1195
                                                        // create direntry ".." to the upper dir
1195
                                                        // create direntry ".." to the upper dir
1196
                                                        dir[1].Name[0] = 0x2E;
1196
                                                        dir[1].Name[0] = 0x2E;
1197
                                                        dir[1].Name[1] = 0x2E;
1197
                                                        dir[1].Name[1] = 0x2E;
1198
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1198
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1199
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
1199
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
1200
                                                        dir[1].StartCluster = dircluster;
1200
                                                        dir[1].StartCluster = dircluster;
1201
                                                        dir[1].DateTime = 0;
1201
                                                        dir[1].DateTime = 0;
1202
                                                        dir[1].Size = 0;
1202
                                                        dir[1].Size = 0;
1203
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1203
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1204
                                                        {
1204
                                                        {
1205
                                                                Fat16_Deinit();
1205
                                                                Fat16_Deinit();
1206
                                                                return(retvalue);
1206
                                                                return(retvalue);
1207
                                                        }
1207
                                                        }
1208
                                                }
1208
                                                }
1209
                                                retvalue = 1;
1209
                                                retvalue = 1;
1210
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1210
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1211
                                        }
1211
                                        }
1212
                                }
1212
                                }
1213
                                dir_sector++; // search next sector
1213
                                dir_sector++; // search next sector
1214
                        // stop if we reached the end of the cluster or the end of the root dir
1214
                        // stop if we reached the end of the cluster or the end of the root dir
1215
                        }while((dir_sector < max_dir_sector) && (!retvalue));
1215
                        }while((dir_sector < max_dir_sector) && (!retvalue));
1216
 
1216
 
1217
                        // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1217
                        // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1218
                        if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1218
                        if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1219
                        {
1219
                        {
1220
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1220
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1221
                        }
1221
                        }
1222
                }while((end_of_directory_not_reached) && (!retvalue));
1222
                }while((end_of_directory_not_reached) && (!retvalue));
1223
                // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
1223
                // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
1224
                // Then we would need to add a cluster to that file and create the new direntry there.
1224
                // Then we would need to add a cluster to that file and create the new direntry there.
1225
                // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1225
                // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1226
                // within a subdirectory of root.
1226
                // within a subdirectory of root.
1227
        }
1227
        }
1228
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1228
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1229
}
1229
}
1230
 
1230
 
1231
/********************************************************************************************************************************************/
1231
/********************************************************************************************************************************************/
1232
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
1232
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
1233
/*                                                                                                                                                                                                                                                                                      */
1233
/*                                                                                                                                                                                                                                                                                      */
1234
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1234
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1235
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
1235
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
1236
/*                                      updated.                                                                                                                                                                                                                                */
1236
/*                                      updated.                                                                                                                                                                                                                                */
1237
/*                                                                                                                                                                                                                                                                                      */
1237
/*                                                                                                                                                                                                                                                                                      */
1238
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1238
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1239
/********************************************************************************************************************************************/
1239
/********************************************************************************************************************************************/
1240
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
1240
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
1241
{
1241
{
1242
        s8* path = 0;
1242
        s8* path = 0;
1243
        s8* subpath = 0;
1243
        s8* subpath = 0;
1244
        u8 af, am, file_exist = 0;
1244
        u8 af, am, file_exist = 0;
1245
        s8 dirname[12]; // 8+3 + temination character
1245
        s8 dirname[12]; // 8+3 + temination character
1246
 
1246
 
1247
        // if incomming pointers are useless return immediatly
1247
        // if incomming pointers are useless return immediatly
1248
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1248
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1249
 
1249
 
1250
        // trace along the filepath
1250
        // trace along the filepath
1251
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1251
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1252
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1252
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1253
        file->DirectoryIndex = 0;
1253
        file->DirectoryIndex = 0;
1254
        // as long as the file was not found and the remaining path is not empty
1254
        // as long as the file was not found and the remaining path is not empty
1255
        while((*path != 0) && !file_exist)
1255
        while((*path != 0) && !file_exist)
1256
        {       // separate dirname and subpath from filepath string
1256
        {       // separate dirname and subpath from filepath string
1257
                subpath = SeperateDirName(path, dirname);
1257
                subpath = SeperateDirName(path, dirname);
1258
                if(subpath != NULL)
1258
                if(subpath != NULL)
1259
                {
1259
                {
1260
                        if(*subpath == 0)
1260
                        if(*subpath == 0)
1261
                        {       // empty subpath indicates last element of dir chain
1261
                        {       // empty subpath indicates last element of dir chain
1262
                                af = attribfilter;
1262
                                af = attribfilter;
1263
                                am = attribmask;
1263
                                am = attribmask;
1264
                        }
1264
                        }
1265
                        else  // it must be a subdirectory and no volume label
1265
                        else  // it must be a subdirectory and no volume label
1266
                        {
1266
                        {
1267
                                af = ATTR_SUBDIRECTORY;
1267
                                af = ATTR_SUBDIRECTORY;
1268
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1268
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1269
                        }
1269
                        }
1270
                        if(!DirectoryEntryExist(dirname, af, am, file))
1270
                        if(!DirectoryEntryExist(dirname, af, am, file))
1271
                        {
1271
                        {
1272
                                return (file_exist); // subdirectory does not exist
1272
                                return (file_exist); // subdirectory does not exist
1273
                        }
1273
                        }
1274
                        else
1274
                        else
1275
                        {
1275
                        {
1276
                                if (*subpath == 0)
1276
                                if (*subpath == 0)
1277
                                {
1277
                                {
1278
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1278
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1279
                                }
1279
                                }
1280
                        }
1280
                        }
1281
                }
1281
                }
1282
                else // error seperating the subpath
1282
                else // error seperating the subpath
1283
                {
1283
                {
1284
                        return file_exist; // bad subdir format
1284
                        return file_exist; // bad subdir format
1285
                }
1285
                }
1286
                path = subpath;
1286
                path = subpath;
1287
                subpath = 0;
1287
                subpath = 0;
1288
        }
1288
        }
1289
        return (file_exist);
1289
        return (file_exist);
1290
}
1290
}
1291
 
1291
 
1292
 
1292
 
1293
/********************************************************************************************************************************************/
1293
/********************************************************************************************************************************************/
1294
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1294
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1295
/*                                                                                                                                                                                                                                                                                      */
1295
/*                                                                                                                                                                                                                                                                                      */
1296
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1296
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1297
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1297
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1298
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1298
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1299
/*                                                                                                                                                                                                                                                                                      */
1299
/*                                                                                                                                                                                                                                                                                      */
1300
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1300
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1301
/********************************************************************************************************************************************/
1301
/********************************************************************************************************************************************/
1302
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1302
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1303
{
1303
{
1304
        s8 *path = 0;
1304
        s8 *path = 0;
1305
        s8 *subpath = 0;
1305
        s8 *subpath = 0;
1306
        u8 af, am, file_created = 0;
1306
        u8 af, am, file_created = 0;
1307
        s8 dirname[12];
1307
        s8 dirname[12];
1308
 
1308
 
1309
        // if incomming pointers are useless return immediatly
1309
        // if incomming pointers are useless return immediatly
1310
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1310
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1311
 
1311
 
1312
        // trace along the filepath
1312
        // trace along the filepath
1313
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
1313
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
1314
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1314
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1315
        file->DirectoryIndex = 0;
1315
        file->DirectoryIndex = 0;
1316
        // as long as the file was not created and the remaining file path is not empty
1316
        // as long as the file was not created and the remaining file path is not empty
1317
        while((*path != 0) && !file_created)
1317
        while((*path != 0) && !file_created)
1318
        {   // separate dirname and subpath from filepath string
1318
        {   // separate dirname and subpath from filepath string
1319
                subpath = SeperateDirName(path, dirname);
1319
                subpath = SeperateDirName(path, dirname);
1320
                if(subpath != NULL)
1320
                if(subpath != NULL)
1321
                {
1321
                {
1322
                        if(*subpath == 0)
1322
                        if(*subpath == 0)
1323
                        {       // empty subpath indicates last element of dir chain
1323
                        {       // empty subpath indicates last element of dir chain
1324
                                af = ATTR_NONE;
1324
                                af = ATTR_NONE;
1325
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1325
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1326
                        }
1326
                        }
1327
                        else  // it must be a subdirectory and no volume label
1327
                        else  // it must be a subdirectory and no volume label
1328
                        {
1328
                        {
1329
                                af = ATTR_SUBDIRECTORY;
1329
                                af = ATTR_SUBDIRECTORY;
1330
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1330
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1331
                        }
1331
                        }
1332
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1332
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1333
                        {  // try to create subdir or file
1333
                        {  // try to create subdir or file
1334
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1334
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1335
                                if(!CreateDirectoryEntry(dirname, af, file))
1335
                                if(!CreateDirectoryEntry(dirname, af, file))
1336
                                {       // could not be created
1336
                                {       // could not be created
1337
                                        return(file_created);
1337
                                        return(file_created);
1338
                                }
1338
                                }
1339
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1339
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1340
                        }
1340
                        }
1341
                }
1341
                }
1342
                else // error seperating the subpath
1342
                else // error seperating the subpath
1343
                {
1343
                {
1344
                        return file_created; // bad subdir format
1344
                        return file_created; // bad subdir format
1345
                }
1345
                }
1346
                path = subpath;
1346
                path = subpath;
1347
                subpath = 0;
1347
                subpath = 0;
1348
        }
1348
        }
1349
        return (file_created);
1349
        return (file_created);
1350
}
1350
}
1351
 
1351
 
1352
 
1352
 
1353
/********************************************************************************************************************************************/
1353
/********************************************************************************************************************************************/
1354
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1354
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1355
/*                                                                                                                                                                                                                                                                                      */
1355
/*                                                                                                                                                                                                                                                                                      */
1356
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1356
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1357
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1357
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1358
/*                                                                                                                                                                                                                                                                                      */
1358
/*                                                                                                                                                                                                                                                                                      */
1359
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1359
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1360
/********************************************************************************************************************************************/
1360
/********************************************************************************************************************************************/
1361
File_t * fopen_(s8 * const filename, const s8 mode)
1361
File_t * fopen_(s8 * const filename, const s8 mode)
1362
{
1362
{
1363
        File_t *file    = 0;
1363
        File_t *file    = 0;
1364
 
1364
 
1365
        if((!Partition.IsValid) || (filename == 0)) return(file);
1365
        if((!Partition.IsValid) || (filename == 0)) return(file);
1366
 
1366
 
1367
        // Look for an unused filepointer in the file pointer list?
1367
        // Look for an unused filepointer in the file pointer list?
1368
        file = LockFilePointer();
1368
        file = LockFilePointer();
1369
        // if no unused file pointer was found return 0
1369
        // if no unused file pointer was found return 0
1370
        if(file == NULL) return(file);
1370
        if(file == NULL) return(file);
1371
 
1371
 
1372
        // now we have found a free filepointer and claimed it
1372
        // now we have found a free filepointer and claimed it
1373
        // so let initiate its property values
1373
        // so let initiate its property values
1374
        file->FirstSectorOfFirstCluster = 0;            // Sectorpointer to the first sector of the first datacluster of the file.
1374
        file->FirstSectorOfFirstCluster = 0;            // Sectorpointer to the first sector of the first datacluster of the file.
1375
        file->FirstSectorOfCurrCluster  = 0;            // Pointer to the cluster which is edited at the moment.
1375
        file->FirstSectorOfCurrCluster  = 0;            // Pointer to the cluster which is edited at the moment.
1376
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1376
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1377
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1377
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1378
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1378
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1379
        file->Size                                              = 0;            // the size of the opened file in bytes.
1379
        file->Size                                              = 0;            // the size of the opened file in bytes.
1380
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1380
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1381
        file->SectorInCache                             = 0;            // the last sector read, wich is still in the sectorbuffer.
1381
        file->SectorInCache                             = 0;            // the last sector read, wich is still in the sectorbuffer.
1382
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1382
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1383
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1383
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1384
        file->Attribute                                 = 0;            // the attribute of the file opened.
1384
        file->Attribute                                 = 0;            // the attribute of the file opened.
1385
 
1385
 
1386
        // check if a real file (no directory) to the given filename exist
1386
        // check if a real file (no directory) to the given filename exist
1387
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1387
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1388
        {  // file exist
1388
        {  // file exist
1389
                switch(mode)  // check mode
1389
                switch(mode)  // check mode
1390
                {
1390
                {
1391
                        case 'a':       // if mode is: append to file
1391
                        case 'a':       // if mode is: append to file
1392
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1392
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1393
                                {       // file is marked as readonly --> do not open this file
1393
                                {       // file is marked as readonly --> do not open this file
1394
                                        fclose_(file);
1394
                                        fclose_(file);
1395
                                        file = NULL;
1395
                                        file = NULL;
1396
                                }
1396
                                }
1397
                                else
1397
                                else
1398
                                {       // file is not marked as read only --> goto end of file
1398
                                {       // file is not marked as read only --> goto end of file
1399
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1399
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1400
                                }
1400
                                }
1401
                                break;
1401
                                break;
1402
                        case 'w':       // if mode is: write to file
1402
                        case 'w':       // if mode is: write to file
1403
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1403
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1404
                                {       // file is marked as readonly --> do not open this file
1404
                                {       // file is marked as readonly --> do not open this file
1405
                                        fclose_(file);
1405
                                        fclose_(file);
1406
                                        file = NULL;
1406
                                        file = NULL;
1407
                                }
1407
                                }
1408
                                else
1408
                                else
1409
                                {       // file is not marked as read only --> goto start of file
1409
                                {       // file is not marked as read only --> goto start of file
1410
                                        // free all clusters of that file
1410
                                        // free all clusters of that file
1411
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1411
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1412
                                        // mar an empy cluster as the last one and store the corresponding sector
1412
                                        // mar an empy cluster as the last one and store the corresponding sector
1413
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file));
1413
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file));
1414
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1414
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1415
                                        file->SectorOfCurrCluster = 0;
1415
                                        file->SectorOfCurrCluster = 0;
1416
                                        file->ByteOfCurrSector = 0;
1416
                                        file->ByteOfCurrSector = 0;
1417
                                        file->Size = 0;
1417
                                        file->Size = 0;
1418
                                        file->Position = 0;
1418
                                        file->Position = 0;
1419
                                        fseek_(file, 0, SEEK_SET);
1419
                                        fseek_(file, 0, SEEK_SET);
1420
                                }
1420
                                }
1421
                                break;
1421
                                break;
1422
                        case 'r':       // if mode is: read from file
1422
                        case 'r':       // if mode is: read from file
1423
                                // goto end of file
1423
                                // goto end of file
1424
                                fseek_(file, 0, SEEK_SET);
1424
                                fseek_(file, 0, SEEK_SET);
1425
                                break;
1425
                                break;
1426
                        default: // other modes are not supported
1426
                        default: // other modes are not supported
1427
                                fclose_(file);
1427
                                fclose_(file);
1428
                                file = NULL;
1428
                                file = NULL;
1429
                        break;
1429
                        break;
1430
                }
1430
                }
1431
                return(file);
1431
                return(file);
1432
        }
1432
        }
1433
        else // file does not exist
1433
        else // file does not exist
1434
        {
1434
        {
1435
                switch(mode)  // check mode
1435
                switch(mode)  // check mode
1436
                {
1436
                {
1437
                        case 'a':
1437
                        case 'a':
1438
                        case 'w': // if mode is write or append
1438
                        case 'w': // if mode is write or append
1439
                                // try to create the file
1439
                                // try to create the file
1440
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1440
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1441
                                { // if it could not be created
1441
                                { // if it could not be created
1442
                                        fclose_(file);
1442
                                        fclose_(file);
1443
                                        file = NULL;
1443
                                        file = NULL;
1444
                                }
1444
                                }
1445
                                break;
1445
                                break;
1446
                        case 'r': // else opened for 'r'
1446
                        case 'r': // else opened for 'r'
1447
                        default:  // of unsupported mode
1447
                        default:  // of unsupported mode
1448
                                fclose_(file);
1448
                                fclose_(file);
1449
                                file = NULL;
1449
                                file = NULL;
1450
                                break;
1450
                                break;
1451
                }
1451
                }
1452
                return(file);
1452
                return(file);
1453
        }
1453
        }
1454
        // we should never come to this point
1454
        // we should never come to this point
1455
        fclose_(file);
1455
        fclose_(file);
1456
        file = NULL;
1456
        file = NULL;
1457
        return(file);
1457
        return(file);
1458
}
1458
}
1459
 
1459
 
1460
/****************************************************************************************************************************************************/
1460
/****************************************************************************************************************************************************/
1461
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1461
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1462
/*                                                                                                                                                                                                                                                                                                      */
1462
/*                                                                                                                                                                                                                                                                                                      */
1463
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1463
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1464
/*                                                                                                                                                                                                                                                                                                      */
1464
/*                                                                                                                                                                                                                                                                                                      */
1465
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1465
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1466
/****************************************************************************************************************************************************/
1466
/****************************************************************************************************************************************************/
1467
s16     fflush_(File_t *file)
1467
s16     fflush_(File_t *file)
1468
{
1468
{
1469
        DirEntry_t *dir;
1469
        DirEntry_t *dir;
1470
 
1470
 
1471
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1471
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1472
 
1472
 
1473
        switch(file->Mode)
1473
        switch(file->Mode)
1474
        {
1474
        {
1475
                case 'a':
1475
                case 'a':
1476
                case 'w':
1476
                case 'w':
1477
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1477
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1478
                        {
1478
                        {
1479
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1479
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1480
                                {
1480
                                {
1481
                                        Fat16_Deinit();
1481
                                        Fat16_Deinit();
1482
                                        return(EOF);
1482
                                        return(EOF);
1483
                                }
1483
                                }
1484
                        }
1484
                        }
1485
                        file->SectorInCache     = file->DirectorySector;
1485
                        file->SectorInCache     = file->DirectorySector;
1486
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1486
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1487
                        {
1487
                        {
1488
                                Fat16_Deinit();
1488
                                Fat16_Deinit();
1489
                                return(EOF);
1489
                                return(EOF);
1490
                        }
1490
                        }
1491
 
1491
 
1492
                        dir = (DirEntry_t *)file->Cache;
1492
                        dir = (DirEntry_t *)file->Cache;
1493
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1493
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1494
                        dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime);         // update date time
1494
                        dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime);         // update date time
1495
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1495
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1496
                        {
1496
                        {
1497
                                Fat16_Deinit();
1497
                                Fat16_Deinit();
1498
                                return(EOF);
1498
                                return(EOF);
1499
                        }
1499
                        }
1500
                        break;
1500
                        break;
1501
                case 'r':
1501
                case 'r':
1502
                default:
1502
                default:
1503
                        return(EOF);
1503
                        return(EOF);
1504
                        break;
1504
                        break;
1505
 
1505
 
1506
        }
1506
        }
1507
        return(0);
1507
        return(0);
1508
}
1508
}
1509
 
1509
 
1510
/****************************************************************************************************************************************/
1510
/****************************************************************************************************************************************/
1511
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1511
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1512
/*                                                                                                                                                                                                                                                                              */
1512
/*                                                                                                                                                                                                                                                                              */
1513
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1513
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1514
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1514
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1515
/*                                                                                                                                                                                                                                                                              */
1515
/*                                                                                                                                                                                                                                                                              */
1516
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1516
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1517
/****************************************************************************************************************************************/
1517
/****************************************************************************************************************************************/
1518
s16 fclose_(File_t *file)
1518
s16 fclose_(File_t *file)
1519
{
1519
{
1520
        s16 returnvalue = EOF;
1520
        s16 returnvalue = EOF;
1521
 
1521
 
1522
        if(file == NULL) return(returnvalue);
1522
        if(file == NULL) return(returnvalue);
1523
        returnvalue = fflush_(file);
1523
        returnvalue = fflush_(file);
1524
        UnlockFilePointer(file);
1524
        UnlockFilePointer(file);
1525
        return(returnvalue);
1525
        return(returnvalue);
1526
}
1526
}
1527
 
1527
 
1528
/********************************************************************************************************************************************/
1528
/********************************************************************************************************************************************/
1529
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1529
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1530
/*                                                                                                                                                                                                                                                                                      */
1530
/*                                                                                                                                                                                                                                                                                      */
1531
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1531
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1532
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1532
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1533
/*                                                                                                                                                                                                                                                                                      */
1533
/*                                                                                                                                                                                                                                                                                      */
1534
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1534
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1535
/********************************************************************************************************************************************/
1535
/********************************************************************************************************************************************/
1536
s16 fgetc_(File_t *file)
1536
s16 fgetc_(File_t *file)
1537
{
1537
{
1538
        s16 c = EOF;
1538
        s16 c = EOF;
1539
        u32 curr_sector;
1539
        u32 curr_sector;
1540
 
1540
 
1541
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1541
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1542
        // if the end of the file is not reached, get the next character.
1542
        // if the end of the file is not reached, get the next character.
1543
        if((0 < file->Size) && ((file->Position+1) < file->Size) )
1543
        if((0 < file->Size) && ((file->Position+1) < file->Size) )
1544
        {
1544
        {
1545
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1545
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1546
                curr_sector += file->SectorOfCurrCluster;
1546
                curr_sector += file->SectorOfCurrCluster;
1547
 
1547
 
1548
                if(file->SectorInCache != curr_sector)
1548
                if(file->SectorInCache != curr_sector)
1549
                {
1549
                {
1550
                        file->SectorInCache = curr_sector;
1550
                        file->SectorInCache = curr_sector;
1551
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1551
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1552
                        {
1552
                        {
1553
                                Fat16_Deinit();
1553
                                Fat16_Deinit();
1554
                                return(c);
1554
                                return(c);
1555
                        }
1555
                        }
1556
                }
1556
                }
1557
                c = (s16) file->Cache[file->ByteOfCurrSector];
1557
                c = (s16) file->Cache[file->ByteOfCurrSector];
1558
                file->Position++;                                                                       // increment file position
1558
                file->Position++;                                                                       // increment file position
1559
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1559
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1560
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1560
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1561
                {
1561
                {
1562
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1562
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1563
                        file->SectorOfCurrCluster++;                                    //      next sector
1563
                        file->SectorOfCurrCluster++;                                    //      next sector
1564
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1564
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1565
                        {
1565
                        {
1566
 
1566
 
1567
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1567
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1568
                                {
1568
                                {
1569
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1569
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1570
                                }
1570
                                }
1571
                                else // the last cluster was allready reached
1571
                                else // the last cluster was allready reached
1572
                                {
1572
                                {
1573
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1573
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1574
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1574
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1575
                                }
1575
                                }
1576
                        }
1576
                        }
1577
                }
1577
                }
1578
        }
1578
        }
1579
        return(c);
1579
        return(c);
1580
}
1580
}
1581
 
1581
 
1582
/********************************************************************************************************************************************/
1582
/********************************************************************************************************************************************/
1583
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1583
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1584
/*                                                                                                                                                                                                                                                                                      */
1584
/*                                                                                                                                                                                                                                                                                      */
1585
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1585
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1586
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1586
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1587
/*                                                                                                                                                                                                                                                                                      */
1587
/*                                                                                                                                                                                                                                                                                      */
1588
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1588
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1589
/********************************************************************************************************************************************/
1589
/********************************************************************************************************************************************/
1590
s16 fputc_(const s8 c, File_t *file)
1590
s16 fputc_(const s8 c, File_t *file)
1591
{
1591
{
1592
        u32 curr_sector  = 0;
1592
        u32 curr_sector  = 0;
1593
 
1593
 
1594
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1594
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1595
 
1595
 
1596
        // If file position equals to file size, then the end of file has reached.
1596
        // If file position equals to file size, then the end of file has reached.
1597
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1597
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1598
        // and a new cluster should be appended.
1598
        // and a new cluster should be appended.
1599
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1599
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1600
        {
1600
        {
1601
                if(!AppendCluster(file)) return(EOF);
1601
                if(!AppendCluster(file)) return(EOF);
1602
        }
1602
        }
1603
 
1603
 
1604
        curr_sector  = file->FirstSectorOfCurrCluster;
1604
        curr_sector  = file->FirstSectorOfCurrCluster;
1605
        curr_sector += file->SectorOfCurrCluster;
1605
        curr_sector += file->SectorOfCurrCluster;
1606
        if(file->SectorInCache != curr_sector)
1606
        if(file->SectorInCache != curr_sector)
1607
        {
1607
        {
1608
                file->SectorInCache = curr_sector;
1608
                file->SectorInCache = curr_sector;
1609
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1609
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1610
                {
1610
                {
1611
                        Fat16_Deinit();
1611
                        Fat16_Deinit();
1612
                        return(EOF);
1612
                        return(EOF);
1613
                }
1613
                }
1614
        }
1614
        }
1615
 
1615
 
1616
        file->Cache[file->ByteOfCurrSector] = (u8)c;                    // write databyte into the buffer. The byte will be written to the device at once
1616
        file->Cache[file->ByteOfCurrSector] = (u8)c;                    // write databyte into the buffer. The byte will be written to the device at once
1617
        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.
1617
        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.
1618
        file->Position++;                                                                       // the actual positon within the file.
1618
        file->Position++;                                                                       // the actual positon within the file.
1619
        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1619
        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1620
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1620
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1621
        {       // save the sector to the sd-card
1621
        {       // save the sector to the sd-card
1622
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1622
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1623
                {
1623
                {
1624
                        Fat16_Deinit();
1624
                        Fat16_Deinit();
1625
                        return(EOF);
1625
                        return(EOF);
1626
                }
1626
                }
1627
                file->ByteOfCurrSector = 0;                                             //  reset byte location
1627
                file->ByteOfCurrSector = 0;                                             //  reset byte location
1628
                file->SectorOfCurrCluster++;                                    //      next sector
1628
                file->SectorOfCurrCluster++;                                    //      next sector
1629
                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1629
                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1630
                {
1630
                {
1631
                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1631
                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1632
                        { // if current cluster was the last cluster of the file
1632
                        { // if current cluster was the last cluster of the file
1633
                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1633
                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1634
                                {
1634
                                {
1635
                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1635
                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1636
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1636
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1637
                                        return(EOF);
1637
                                        return(EOF);
1638
                                }
1638
                                }
1639
                        }
1639
                        }
1640
                        else // next cluster
1640
                        else // next cluster
1641
                        {
1641
                        {
1642
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1642
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1643
                        }
1643
                        }
1644
                }
1644
                }
1645
        }
1645
        }
1646
        return(0);
1646
        return(0);
1647
}
1647
}
1648
 
1648
 
1649
 
1649
 
1650
/****************************************************************************************************************************************/
1650
/****************************************************************************************************************************************/
1651
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1651
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1652
/*                                                                                                                                                                                                                                                                              */
1652
/*                                                                                                                                                                                                                                                                              */
1653
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1653
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1654
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1654
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1655
/*                                                                                                                                                                                                                                                                              */
1655
/*                                                                                                                                                                                                                                                                              */
1656
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1656
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1657
/****************************************************************************************************************************************/
1657
/****************************************************************************************************************************************/
1658
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1658
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1659
{
1659
{
1660
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1660
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1661
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1661
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1662
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1662
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1663
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1663
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1664
        s16 c;
1664
        s16 c;
1665
 
1665
 
1666
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1666
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1667
 
1667
 
1668
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1668
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1669
 
1669
 
1670
        while((object_cnt < count) && success)
1670
        while((object_cnt < count) && success)
1671
        {
1671
        {
1672
                object_size = size;
1672
                object_size = size;
1673
                while((size > 0) && success)
1673
                while((size > 0) && success)
1674
                {
1674
                {
1675
                        c = fgetc_(file);
1675
                        c = fgetc_(file);
1676
                        if(c != EOF)
1676
                        if(c != EOF)
1677
                        {
1677
                        {
1678
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1678
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1679
                                pbuff++;
1679
                                pbuff++;
1680
                                size--;
1680
                                size--;
1681
                        }
1681
                        }
1682
                        else // error or end of file reached
1682
                        else // error or end of file reached
1683
                        {
1683
                        {
1684
                                success = 0;
1684
                                success = 0;
1685
                        }
1685
                        }
1686
                }
1686
                }
1687
                if(success) object_cnt++;
1687
                if(success) object_cnt++;
1688
        }
1688
        }
1689
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1689
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1690
}
1690
}
1691
 
1691
 
1692
 
1692
 
1693
/****************************************************************************************************************************************/
1693
/****************************************************************************************************************************************/
1694
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1694
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1695
/*                                                                                                                                                                                                                                                                              */
1695
/*                                                                                                                                                                                                                                                                              */
1696
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1696
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1697
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1697
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1698
/*                                                                                                                                                                                                                                                                              */
1698
/*                                                                                                                                                                                                                                                                              */
1699
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1699
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1700
/****************************************************************************************************************************************/
1700
/****************************************************************************************************************************************/
1701
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
1701
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
1702
{
1702
{
1703
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1703
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1704
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
1704
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
1705
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1705
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1706
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1706
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1707
        s16 c;
1707
        s16 c;
1708
 
1708
 
1709
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1709
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1710
 
1710
 
1711
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1711
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1712
 
1712
 
1713
        while((object_cnt < count) && success)
1713
        while((object_cnt < count) && success)
1714
        {
1714
        {
1715
                object_size = size;
1715
                object_size = size;
1716
                while((size > 0) && success)
1716
                while((size > 0) && success)
1717
                {
1717
                {
1718
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1718
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1719
                        if(c != EOF)
1719
                        if(c != EOF)
1720
                        {
1720
                        {
1721
                                pbuff++;
1721
                                pbuff++;
1722
                                size--;
1722
                                size--;
1723
                        }
1723
                        }
1724
                        else
1724
                        else
1725
                        {
1725
                        {
1726
                                success = 0;
1726
                                success = 0;
1727
                        }
1727
                        }
1728
                }
1728
                }
1729
                if(success) object_cnt++;
1729
                if(success) object_cnt++;
1730
        }
1730
        }
1731
 
1731
 
1732
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1732
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1733
}
1733
}
1734
 
1734
 
1735
 
1735
 
1736
/****************************************************************************************************************************************/
1736
/****************************************************************************************************************************************/
1737
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1737
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1738
/*                                                                                                                                                                                                                                                                              */
1738
/*                                                                                                                                                                                                                                                                              */
1739
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1739
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1740
/*                                                                                                                                                                                                                                                                              */
1740
/*                                                                                                                                                                                                                                                                              */
1741
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1741
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1742
/****************************************************************************************************************************************/
1742
/****************************************************************************************************************************************/
1743
s16 fputs_(s8 * const string, File_t * const file)
1743
s16 fputs_(s8 * const string, File_t * const file)
1744
{
1744
{
1745
        u8 i=0;
1745
        u8 i=0;
1746
        s16 c = 0;
1746
        s16 c = 0;
1747
 
1747
 
1748
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
1748
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
1749
 
1749
 
1750
        while((string[i] != 0)&& (c != EOF))
1750
        while((string[i] != 0)&& (c != EOF))
1751
        {
1751
        {
1752
                c = fputc_(string[i], file);
1752
                c = fputc_(string[i], file);
1753
                i++;
1753
                i++;
1754
        }
1754
        }
1755
        return(c);
1755
        return(c);
1756
}
1756
}
1757
 
1757
 
1758
/****************************************************************************************************************************************/
1758
/****************************************************************************************************************************************/
1759
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
1759
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
1760
/*                                                                                                                                                                                                                                                                              */
1760
/*                                                                                                                                                                                                                                                                              */
1761
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1761
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1762
/*                                                                                                                                                                                                                                                                              */
1762
/*                                                                                                                                                                                                                                                                              */
1763
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1763
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1764
/****************************************************************************************************************************************/
1764
/****************************************************************************************************************************************/
1765
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
1765
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
1766
{
1766
{
1767
        s8 *pbuff;
1767
        s8 *pbuff;
1768
        s16 c = 0, bytecount;
1768
        s16 c = 0, bytecount;
1769
 
1769
 
1770
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
1770
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
1771
        bytecount = length;
1771
        bytecount = length;
1772
        pbuff = string;                                                         // set write pointer to start of string
1772
        pbuff = string;                                                         // set write pointer to start of string
1773
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
1773
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
1774
        {
1774
        {
1775
                c = fgetc_(file);                                               // read a character from the opened file.
1775
                c = fgetc_(file);                                               // read a character from the opened file.
1776
                switch(c)
1776
                switch(c)
1777
                {
1777
                {
1778
                        case 0x0A:                                                      // new line
1778
                        case 0x0A:                                                      // new line
1779
                                *pbuff = 0;                                             // set string terminator
1779
                                *pbuff = 0;                                             // set string terminator
1780
                                return(string);                                 // return normal
1780
                                return(string);                                 // return normal
1781
 
1781
 
1782
                        case EOF:
1782
                        case EOF:
1783
                                *pbuff = 0;                                             // set string terminator
1783
                                *pbuff = 0;                                             // set string terminator
1784
                                return(0);
1784
                                return(0);
1785
 
1785
 
1786
                        default:
1786
                        default:
1787
                                *pbuff++ = (s8)c;                               // copy byte to string
1787
                                *pbuff++ = (s8)c;                               // copy byte to string
1788
                                bytecount--;
1788
                                bytecount--;
1789
                                break;
1789
                                break;
1790
                }
1790
                }
1791
        }
1791
        }
1792
        *pbuff = 0;     // set string terminator
1792
        *pbuff = 0;     // set string terminator
1793
        return(string);
1793
        return(string);
1794
}
1794
}
1795
 
1795
 
1796
/****************************************************************************************************************************************/
1796
/****************************************************************************************************************************************/
1797
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
1797
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
1798
/*                                                                                                                                                                                                                                                                              */
1798
/*                                                                                                                                                                                                                                                                              */
1799
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1799
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1800
/*                                                                                                                                                                                                                                                                              */
1800
/*                                                                                                                                                                                                                                                                              */
1801
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1801
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1802
/****************************************************************************************************************************************/
1802
/****************************************************************************************************************************************/
1803
u8 fexist_(s8 * const filename)
1803
u8 fexist_(s8 * const filename)
1804
{
1804
{
1805
        u8 exist = 0;
1805
        u8 exist = 0;
1806
        File_t *file = 0;
1806
        File_t *file = 0;
1807
        file = LockFilePointer();
1807
        file = LockFilePointer();
1808
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1808
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1809
        UnlockFilePointer(file);
1809
        UnlockFilePointer(file);
1810
        return(exist);
1810
        return(exist);
1811
}
1811
}
1812
 
1812
 
1813
/****************************************************************************************************************************************/
1813
/****************************************************************************************************************************************/
1814
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1814
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1815
/*                                                                                                                                                                                                                                                                              */
1815
/*                                                                                                                                                                                                                                                                              */
1816
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1816
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1817
/*                                                                                                                                                                                                                                                                              */
1817
/*                                                                                                                                                                                                                                                                              */
1818
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1818
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1819
/****************************************************************************************************************************************/
1819
/****************************************************************************************************************************************/
1820
u8 feof_(File_t *file)
1820
u8 feof_(File_t *file)
1821
{
1821
{
1822
        if(((file->Position)+1) < (file->Size))
1822
        if(((file->Position)+1) < (file->Size))
1823
        {
1823
        {
1824
                return(0);
1824
                return(0);
1825
        }
1825
        }
1826
        else
1826
        else
1827
        {
1827
        {
1828
                return(1);
1828
                return(1);
1829
        }
1829
        }
1830
}
1830
}
1831
 
1831
 
1832
 
1832
 
1833
 
1833