Subversion Repositories NaviCtrl

Rev

Rev 219 | Rev 304 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 219 Rev 282
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 / NON-COMMERCIAL USE ONLY
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 oder Nutzung 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 the sources to other systems or using the software on other systems (except 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 "timer1.h"
59
#include "timer1.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
// Module name:                 fat16.c
65
// Module name:                 fat16.c
66
// Compiler used:               avr-gcc 3.4.5
66
// Compiler used:               avr-gcc 3.4.5
67
// Last Modifikation:   20.03.2010
67
// Last Modifikation:   20.03.2010
68
// Version:                             2.10
68
// Version:                             2.10
69
// Authors:                             Stephan Busker & Gregor Stobrawa
69
// Authors:                             Stephan Busker & Gregor Stobrawa
70
// Description:                 Source files for FAT16 implementation with read and write-access
70
// Description:                 Source files for FAT16 implementation with read and write-access
71
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
71
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
72
//........................................................................................................................................
72
//........................................................................................................................................
73
// Functions:                   extern s16              Fat16_Init(void);
73
// Functions:                   extern s16              Fat16_Init(void);
74
//                                              extern s16              Fat16_Deinit(void);
74
//                                              extern s16              Fat16_Deinit(void);
75
//                                              extern s8*              FAT16_GetVolumeLabel(void);
75
//                                              extern s8*              FAT16_GetVolumeLabel(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 u8               fexist_(s8 * const filename);
78
//                                              extern u8               fexist_(s8 * const filename);
79
//                                              extern s16              fflush_(File_t *File);
79
//                                              extern s16              fflush_(File_t *File);
80
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
80
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
81
//                                              extern s16              fgetc_(File_t *File);
81
//                                              extern s16              fgetc_(File_t *File);
82
//                                              extern s16              fputc_(u8 c, File_t *File);
82
//                                              extern s16              fputc_(u8 c, File_t *File);
83
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File);
83
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File);
84
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
84
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
85
//                                              extern s16              fputs_(const u8 *string, File_t *File);
85
//                                              extern s16              fputs_(const u8 *string, File_t *File);
86
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
86
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
87
//                                              extern u8               feof_(File_t * const file);
87
//                                              extern u8               feof_(File_t * const file);
88
//........................................................................................................................................
88
//........................................................................................................................................
89
// ext. functions:              extern SD_Result_t SDC_Init(void;)
89
// ext. functions:              extern SD_Result_t SDC_Init(void;)
90
//                                              extern SD_Result_t SDC_Deinit(void);
90
//                                              extern SD_Result_t SDC_Deinit(void);
91
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);
91
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);
92
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
92
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
93
//........................................................................................................................................
93
//........................................................................................................................................
94
//
94
//
95
// URL:                                 www.Mikro-Control.de
95
// URL:                                 www.Mikro-Control.de
96
// mailto:                              stephan.busker@mikro-control.de
96
// mailto:                              stephan.busker@mikro-control.de
97
//________________________________________________________________________________________________________________________________________
97
//________________________________________________________________________________________________________________________________________
98
 
98
 
99
/*
99
/*
100
FAT16 Drive Layout:
100
FAT16 Drive Layout:
101
Description                                             Offset
101
Description                                             Offset
102
Volume Boot Sector                                      Start of Partition
102
Volume Boot Sector                                      Start of Partition
103
Fat Tables                                                      Start + # of Reserved Sectors
103
Fat Tables                                                      Start + # of Reserved Sectors
104
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
104
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
105
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
105
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
106
*/
106
*/
107
 
107
 
108
 
108
 
109
/*
109
/*
110
________________________________________________________________________________________________________________________________________
110
________________________________________________________________________________________________________________________________________
111
 
111
 
112
        Structure of an partition entry
112
        Structure of an partition entry
113
________________________________________________________________________________________________________________________________________
113
________________________________________________________________________________________________________________________________________
114
 
114
 
115
        Partition Entry is 16 bytes long
115
        Partition Entry is 16 bytes long
116
*/
116
*/
117
typedef struct
117
typedef struct
118
{
118
{
119
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
119
        u8      PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
120
        u8      BeginningHead;                          // Beginning of Partition - Head
120
        u8      BeginningHead;                          // Beginning of Partition - Head
121
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
121
        u16     BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
122
        u8      Type;                                           // Type of Partition (See List Below)
122
        u8      Type;                                           // Type of Partition (See List Below)
123
        u8      EndHead;                                        // End of Partition - Head
123
        u8      EndHead;                                        // End of Partition - Head
124
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
124
        u16     EndCylSec;                                      // End of Partition - Cylinder/Sector
125
        u32     NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
125
        u32     NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
126
        u32     NoSectorsPartition      ;               // Number of Sectors in the Partition
126
        u32     NoSectorsPartition      ;               // Number of Sectors in the Partition
127
} __attribute__((packed)) PartitionEntry_t;
127
} __attribute__((packed)) PartitionEntry_t;
128
 
128
 
129
/*
129
/*
130
Coding of Cylinder/Sector words
130
Coding of Cylinder/Sector words
131
 
131
 
132
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
132
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
133
Sector is 5 bits:  [5:0] at [5:0]
133
Sector is 5 bits:  [5:0] at [5:0]
134
*/
134
*/
135
 
135
 
136
// Partition Types:
136
// Partition Types:
137
#define PART_TYPE_UNKNOWN                       0x00
137
#define PART_TYPE_UNKNOWN                       0x00
138
#define PART_TYPE_FAT12                         0x01
138
#define PART_TYPE_FAT12                         0x01
139
#define PART_TYPE_XENIX                         0x02
139
#define PART_TYPE_XENIX                         0x02
140
#define PART_TYPE_FAT16_ST_32_MB        0x04
140
#define PART_TYPE_FAT16_ST_32_MB        0x04
141
#define PART_TYPE_EXTDOS                        0x05
141
#define PART_TYPE_EXTDOS                        0x05
142
#define PART_TYPE_FAT16_LT_32_MB        0x06
142
#define PART_TYPE_FAT16_LT_32_MB        0x06
143
#define PART_TYPE_NTFS                          0x07
143
#define PART_TYPE_NTFS                          0x07
144
#define PART_TYPE_FAT32                         0x0B
144
#define PART_TYPE_FAT32                         0x0B
145
#define PART_TYPE_FAT32LBA                      0x0C
145
#define PART_TYPE_FAT32LBA                      0x0C
146
#define PART_TYPE_FAT16LBA                      0x0E
146
#define PART_TYPE_FAT16LBA                      0x0E
147
#define PART_TYPE_EXTDOSLBA                     0x0F
147
#define PART_TYPE_EXTDOSLBA                     0x0F
148
#define PART_TYPE_EISA                          0x12
148
#define PART_TYPE_EISA                          0x12
149
#define PART_TYPE_ONTRACK                       0x33
149
#define PART_TYPE_ONTRACK                       0x33
150
#define PART_TYPE_NOVELL                        0x40
150
#define PART_TYPE_NOVELL                        0x40
151
#define PART_TYPE_DYNAMIC                       0x42
151
#define PART_TYPE_DYNAMIC                       0x42
152
#define PART_TYPE_PCIX                          0x4B
152
#define PART_TYPE_PCIX                          0x4B
153
#define PART_TYPE_LINUX_SWAP            0x82
153
#define PART_TYPE_LINUX_SWAP            0x82
154
#define PART_TYPE_LINUX_NATIVE          0x83
154
#define PART_TYPE_LINUX_NATIVE          0x83
155
#define PART_TYPE_LINUX_LVM                     0x8E
155
#define PART_TYPE_LINUX_LVM                     0x8E
156
#define PART_TYPE_PHOENIXSAVE           0xA0
156
#define PART_TYPE_PHOENIXSAVE           0xA0
157
#define PART_TYPE_FREEBSD                       0xA5
157
#define PART_TYPE_FREEBSD                       0xA5
158
#define PART_TYPE_OPENBSD                       0xA6
158
#define PART_TYPE_OPENBSD                       0xA6
159
#define PART_TYPE_NETNBSD                       0xA9
159
#define PART_TYPE_NETNBSD                       0xA9
160
#define PART_TYPE_CPM                           0xDB
160
#define PART_TYPE_CPM                           0xDB
161
#define PART_TYPE_DBFS                          0xE0
161
#define PART_TYPE_DBFS                          0xE0
162
#define PART_TYPE_BBT                           0xFF
162
#define PART_TYPE_BBT                           0xFF
163
 
163
 
164
 
164
 
165
/*
165
/*
166
________________________________________________________________________________________________________________________________________
166
________________________________________________________________________________________________________________________________________
167
 
167
 
168
        Structure of the MasterBootRecord
168
        Structure of the MasterBootRecord
169
________________________________________________________________________________________________________________________________________
169
________________________________________________________________________________________________________________________________________
170
 
170
 
171
        Master Boot Record is 512 bytes long
171
        Master Boot Record is 512 bytes long
172
        The Master Boot Record is the same for pretty much all Operating Systems.
172
        The Master Boot Record is the same for pretty much all Operating Systems.
173
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
173
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
174
*/
174
*/
175
typedef struct
175
typedef struct
176
{
176
{
177
        u8                              ExecutableCode[446];    // 446 bytes for machine start code
177
        u8                              ExecutableCode[446];    // 446 bytes for machine start code
178
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1
178
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1
179
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2
179
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2
180
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3
180
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3
181
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4
181
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4
182
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)
182
        u16                                     ExecutableMarker;               // BIOS-Signature (0x55 0xAA)
183
} __attribute__((packed)) MBR_Entry_t;
183
} __attribute__((packed)) MBR_Entry_t;
184
 
184
 
185
 
185
 
186
/*
186
/*
187
________________________________________________________________________________________________________________________________________
187
________________________________________________________________________________________________________________________________________
188
 
188
 
189
        Structure of the VolumeBootRecord
189
        Structure of the VolumeBootRecord
190
________________________________________________________________________________________________________________________________________
190
________________________________________________________________________________________________________________________________________
191
 
191
 
192
        The Volume Boot Record is 512 bytes long
192
        The Volume Boot Record is 512 bytes long
193
        This information is located in the first sector of every partition.
193
        This information is located in the first sector of every partition.
194
*/
194
*/
195
typedef struct
195
typedef struct
196
{
196
{
197
        u8  JumpCode[3];                        // Jump Code + NOP
197
        u8  JumpCode[3];                        // Jump Code + NOP
198
        s8  OEMName[8];                         // OEM Name
198
        s8  OEMName[8];                         // OEM Name
199
        u16 BytesPerSector;                     // Bytes Per Sector
199
        u16 BytesPerSector;                     // Bytes Per Sector
200
        u8  SectorsPerCluster;          // Sectors Per Cluster
200
        u8  SectorsPerCluster;          // Sectors Per Cluster
201
        u16 ReservedSectors;            // Reserved Sectors
201
        u16 ReservedSectors;            // Reserved Sectors
202
        u8  NoFATCopies;                        // Number of Copies of FAT
202
        u8  NoFATCopies;                        // Number of Copies of FAT
203
        u16 MaxRootEntries;                     // Maximum Root Directory Entries
203
        u16 MaxRootEntries;                     // Maximum Root Directory Entries
204
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
204
        u16 NoSectorsInPartSml32MB;     // Number of Sectors in Partition Smaller than 32 MB
205
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
205
        u8  MediaDescriptor;            // Media Descriptor (0xF8 for Hard Disks)
206
        u16 SectorsPerFAT;                      // Sectors Per FAT
206
        u16 SectorsPerFAT;                      // Sectors Per FAT
207
        u16 SectorsPerTrack;            // Sectors Per Track
207
        u16 SectorsPerTrack;            // Sectors Per Track
208
        u16 NoHeads;                            // Number of Heads
208
        u16 NoHeads;                            // Number of Heads
209
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
209
        u32 NoHiddenSectors;            // Number of Hidden Sectors     in Partition
210
        u32 NoSectors;                          // Number of Sectors in Partition
210
        u32 NoSectors;                          // Number of Sectors in Partition
211
        u16     DriveNo;                                // Logical Drive Number of Partition
211
        u16     DriveNo;                                // Logical Drive Number of Partition
212
        u8  ExtendedSig;                        // Extended Signature (0x29)
212
        u8  ExtendedSig;                        // Extended Signature (0x29)
213
        u32 SerialNo;                           // Serial Number of the Partition
213
        u32 SerialNo;                           // Serial Number of the Partition
214
        s8  VolumeName[11];                     // Volume Name of the Partititon
214
        s8  VolumeName[11];                     // Volume Name of the Partititon
215
        s8  FATName[8];                         // FAT Name (FAT16)
215
        s8  FATName[8];                         // FAT Name (FAT16)
216
        u8  ExecutableCode[446];        // 446 bytes for machine start code
216
        u8  ExecutableCode[446];        // 446 bytes for machine start code
217
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)
217
        u16 ExecutableMarker;           // Executable Marker (0x55 0xAA)
218
} __attribute__((packed)) VBR_Entry_t;
218
} __attribute__((packed)) VBR_Entry_t;
219
 
219
 
220
 
220
 
221
 
221
 
222
/*
222
/*
223
________________________________________________________________________________________________________________________________________
223
________________________________________________________________________________________________________________________________________
224
 
224
 
225
        Structure of an directory entry
225
        Structure of an directory entry
226
________________________________________________________________________________________________________________________________________
226
________________________________________________________________________________________________________________________________________
227
 
227
 
228
        Directory entry is 32 bytes.
228
        Directory entry is 32 bytes.
229
*/
229
*/
230
typedef struct
230
typedef struct
231
{
231
{
232
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
232
        s8      Name[8];                                        // 8 bytes name, padded with spaces.
233
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
233
        u8      Extension[3];                           // 3 bytes extension, padded with spaces.
234
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
234
        u8      Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
235
        u8  Res1;                                               // should be zero
235
        u8  Res1;                                               // should be zero
236
        u8  CreationTime10ms;                   // subsecond resolution of creation time
236
        u8  CreationTime10ms;                   // subsecond resolution of creation time
237
        u16 CreationTime;                               // Time of creation h:m:s
237
        u16 CreationTime;                               // Time of creation h:m:s
238
        u16 CreationDate;                               // Date of creation Y.M.D
238
        u16 CreationDate;                               // Date of creation Y.M.D
239
        u16 LastAccessDate;             // The date where the file was last accessed
239
        u16 LastAccessDate;             // The date where the file was last accessed
240
        u8      Res2[2];                                    // should be zero
240
        u8      Res2[2];                                    // should be zero
241
        u16 ModTime;                                    // date of last write access
241
        u16 ModTime;                                    // date of last write access
242
        u16 ModDate;                                    // date of last write access to the file or directory.
242
        u16 ModDate;                                    // date of last write access to the file or directory.
243
        u16 StartCluster;                               // first cluster of the file or directory.
243
        u16 StartCluster;                               // first cluster of the file or directory.
244
        u32 Size;                                               // size of the file or directory in bytes.
244
        u32 Size;                                               // size of the file or directory in bytes.
245
}  __attribute__((packed)) DirEntry_t;
245
}  __attribute__((packed)) DirEntry_t;
246
 
246
 
247
#define SLOT_EMPTY              0x00    // slot has never been used
247
#define SLOT_EMPTY              0x00    // slot has never been used
248
#define SLOT_E5                 0x05    // the real value is 0xe5
248
#define SLOT_E5                 0x05    // the real value is 0xe5
249
#define SLOT_DELETED            0xE5    // file in this slot deleted
249
#define SLOT_DELETED            0xE5    // file in this slot deleted
250
 
250
 
251
#define ATTR_NONE               0x00    // normal file
251
#define ATTR_NONE               0x00    // normal file
252
#define ATTR_READONLY           0x01    // file is readonly
252
#define ATTR_READONLY           0x01    // file is readonly
253
#define ATTR_HIDDEN                     0x02    // file is hidden
253
#define ATTR_HIDDEN                     0x02    // file is hidden
254
#define ATTR_SYSTEM                     0x04    // file is a system file
254
#define ATTR_SYSTEM                     0x04    // file is a system file
255
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
255
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
256
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
256
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
257
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
257
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
258
#define ATTR_ARCHIVE            0x20    // file is new or modified
258
#define ATTR_ARCHIVE            0x20    // file is new or modified
259
 
259
 
260
 
260
 
261
/*
261
/*
262
________________________________________________________________________________________________________________________________________
262
________________________________________________________________________________________________________________________________________
263
 
263
 
264
        Structure of an entry within the fileallocationtable.
264
        Structure of an entry within the fileallocationtable.
265
________________________________________________________________________________________________________________________________________
265
________________________________________________________________________________________________________________________________________
266
*/
266
*/
267
typedef struct
267
typedef struct
268
{
268
{
269
        u16  NextCluster;                               // the next cluster of the file.
269
        u16  NextCluster;                               // the next cluster of the file.
270
} __attribute__((packed)) Fat16Entry_t;
270
} __attribute__((packed)) Fat16Entry_t;
271
 
271
 
272
// secial fat entries
272
// secial fat entries
273
#define FAT16_CLUSTER_FREE                      0x0000
273
#define FAT16_CLUSTER_FREE                      0x0000
274
#define FAT16_CLUSTER_RESERVED          0x0001
274
#define FAT16_CLUSTER_RESERVED          0x0001
275
#define FAT16_CLUSTER_USED_MIN          0x0002
275
#define FAT16_CLUSTER_USED_MIN          0x0002
276
#define FAT16_CLUSTER_USED_MAX          0xFFEF
276
#define FAT16_CLUSTER_USED_MAX          0xFFEF
277
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
277
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
278
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
278
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
279
#define FAT16_CLUSTER_BAD                       0xFFF7
279
#define FAT16_CLUSTER_BAD                       0xFFF7
280
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
280
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
281
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
281
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
282
 
282
 
283
/*****************************************************************************************************************************************/
283
/*****************************************************************************************************************************************/
284
/*                                                                                                                                                                                                                                                                               */
284
/*                                                                                                                                                                                                                                                                               */
285
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
285
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
286
/*                                                                                                                                                                                                                                                                               */
286
/*                                                                                                                                                                                                                                                                               */
287
/*****************************************************************************************************************************************/
287
/*****************************************************************************************************************************************/
288
 
288
 
289
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
289
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
290
#define DIRENTRY_SIZE                           32              //bytes
290
#define DIRENTRY_SIZE                           32              //bytes
291
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
291
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
292
#define FAT16_BYTES                                     2
292
#define FAT16_BYTES                                     2
293
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
293
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
294
 
294
 
295
#define SECTOR_UNDEFINED        0x00000000L
295
#define SECTOR_UNDEFINED        0x00000000L
296
#define CLUSTER_UNDEFINED       0x0000
296
#define CLUSTER_UNDEFINED       0x0000
297
 
297
 
298
#define FSTATE_UNUSED   0
298
#define FSTATE_UNUSED   0
299
#define FSTATE_USED             1
299
#define FSTATE_USED             1
300
 
300
 
301
typedef struct
301
typedef struct
302
{
302
{
303
        u8      IsValid;                                // 0 means invalid, else valid
303
        u8      IsValid;                                // 0 means invalid, else valid
304
        u8      SectorsPerCluster;              // how many sectors does a cluster contain?
304
        u8      SectorsPerCluster;              // how many sectors does a cluster contain?
305
        u8      FatCopies;                              // Numbers of copies of the FAT
305
        u8      FatCopies;                              // Numbers of copies of the FAT
306
        u16     MaxRootEntries;                 // Possible number of entries in the root directory.
306
        u16     MaxRootEntries;                 // Possible number of entries in the root directory.
307
        u16     SectorsPerFat;                  // how many sectors does a fat16 contain?
307
        u16     SectorsPerFat;                  // how many sectors does a fat16 contain?
308
        u32 FirstFatSector;                     // sector of the start of the fat
308
        u32 FirstFatSector;                     // sector of the start of the fat
309
        u32 FirstRootDirSector;         // sector of the rootdirectory
309
        u32 FirstRootDirSector;         // sector of the rootdirectory
310
        u32 FirstDataSector;            // sector of the first cluster containing data (cluster2).
310
        u32 FirstDataSector;            // sector of the first cluster containing data (cluster2).
311
        u32 LastDataSector;                     // the last data sector of the partition
311
        u32 LastDataSector;                     // the last data sector of the partition
312
        u8 VolumeLabel[12];                     // the volume label
312
        u8 VolumeLabel[12];                     // the volume label
313
} Partition_t;
313
} Partition_t;
314
 
314
 
315
Partition_t     Partition;                                      // Structure holds partition information
315
Partition_t     Partition;                                      // Structure holds partition information
316
 
316
 
317
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
317
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
318
 
318
 
319
 
319
 
320
/****************************************************************************************************************************************/
320
/****************************************************************************************************************************************/
321
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
321
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
322
/*                                                                                                                                                                                                                                                                              */
322
/*                                                                                                                                                                                                                                                                              */
323
/*      Description:    This function calculates the DOS date from a pointer to a time structure.                                                                                       */
323
/*      Description:    This function calculates the DOS date from a pointer to a time structure.                                                                                       */
324
/*                                                                                                                                                                                                                                                                              */
324
/*                                                                                                                                                                                                                                                                              */
325
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
325
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
326
/****************************************************************************************************************************************/
326
/****************************************************************************************************************************************/
327
u16 FileDate(DateTime_t * pTimeStruct)
327
u16 FileDate(DateTime_t * pTimeStruct)
328
{
328
{
329
        u16 date = 0;
329
        u16 date = 0;
330
        if(pTimeStruct == NULL)   return date;
330
        if(pTimeStruct == NULL)   return date;
331
        if(!(pTimeStruct->Valid)) return date;
331
        if(!(pTimeStruct->Valid)) return date;
332
 
332
 
333
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
333
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
334
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
334
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
335
        date |= (0x001F & (u16)(pTimeStruct->Day));
335
        date |= (0x001F & (u16)(pTimeStruct->Day));
336
        return date;
336
        return date;
337
}
337
}
338
 
338
 
339
/****************************************************************************************************************************************/
339
/****************************************************************************************************************************************/
340
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
340
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
341
/*                                                                                                                                                                                                                                                                              */
341
/*                                                                                                                                                                                                                                                                              */
342
/*      Description:    This function calculates the DOS time from a pointer to a time structure.                                                                                       */
342
/*      Description:    This function calculates the DOS time from a pointer to a time structure.                                                                                       */
343
/*                                                                                                                                                                                                                                                                              */
343
/*                                                                                                                                                                                                                                                                              */
344
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
344
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
345
/****************************************************************************************************************************************/
345
/****************************************************************************************************************************************/
346
 
346
 
347
u16 FileTime(DateTime_t * pTimeStruct)
347
u16 FileTime(DateTime_t * pTimeStruct)
348
{
348
{
349
        u16 time = 0;
349
        u16 time = 0;
350
        if(pTimeStruct == NULL)   return time;
350
        if(pTimeStruct == NULL)   return time;
351
        if(!(pTimeStruct->Valid)) return time;
351
        if(!(pTimeStruct->Valid)) return time;
352
 
352
 
353
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
353
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
354
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
354
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
355
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
355
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
356
        return time;
356
        return time;
357
}
357
}
358
 
358
 
359
/****************************************************************************************************************************************/
359
/****************************************************************************************************************************************/
360
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
360
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
361
/*                                                                                                                                                                                                                                                                              */
361
/*                                                                                                                                                                                                                                                                              */
362
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
362
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
363
/*                                                                                                                                                                                                                                                                              */
363
/*                                                                                                                                                                                                                                                                              */
364
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
364
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
365
/****************************************************************************************************************************************/
365
/****************************************************************************************************************************************/
366
File_t * LockFilePointer(void)
366
File_t * LockFilePointer(void)
367
{
367
{
368
        u8 i;
368
        u8 i;
369
        File_t * File = 0;
369
        File_t * File = 0;
370
        for(i = 0; i < FILE_MAX_OPEN; i++)
370
        for(i = 0; i < FILE_MAX_OPEN; i++)
371
        {
371
        {
372
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one
372
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one
373
                {
373
                {
374
                        File = &FilePointer[i];                                         // set pointer to that entry
374
                        File = &FilePointer[i];                                         // set pointer to that entry
375
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
375
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
376
                        break;
376
                        break;
377
                }
377
                }
378
        }
378
        }
379
        return(File);
379
        return(File);
380
}
380
}
381
 
381
 
382
/****************************************************************************************************************************************/
382
/****************************************************************************************************************************************/
383
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
383
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
384
/*                                                                                                                                                                                                                                                                              */
384
/*                                                                                                                                                                                                                                                                              */
385
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
385
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
386
/*                                                                                                                                                                                                                                                                              */
386
/*                                                                                                                                                                                                                                                                              */
387
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
387
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
388
/****************************************************************************************************************************************/
388
/****************************************************************************************************************************************/
389
u8 UnlockFilePointer(File_t * file)
389
u8 UnlockFilePointer(File_t * file)
390
{
390
{
391
        u8 cnt;
391
        u8 cnt;
392
        if(file == NULL) return(0);
392
        if(file == NULL) return(0);
393
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
393
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
394
        {
394
        {
395
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
395
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
396
                {
396
                {
397
                        file->State = FSTATE_UNUSED;
397
                        file->State = FSTATE_UNUSED;
398
                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;                     // Sectorpointer to the first sector of the first datacluster of the file.
398
                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;                     // Sectorpointer to the first sector of the first datacluster of the file.
399
                        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;                     // Pointer to the cluster which is edited at the moment.
399
                        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;                     // Pointer to the cluster which is edited at the moment.
400
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
400
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
401
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
401
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
402
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
402
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
403
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
403
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
404
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
404
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
405
                        file->SectorInCache                     = SECTOR_UNDEFINED;                     // the last sector read, wich is still in the sectorbuffer.
405
                        file->SectorInCache                     = SECTOR_UNDEFINED;                     // the last sector read, wich is still in the sectorbuffer.
406
                        file->DirectorySector                   = SECTOR_UNDEFINED;                     // the sectorposition where the directoryentry has been made.
406
                        file->DirectorySector                   = SECTOR_UNDEFINED;                     // the sectorposition where the directoryentry has been made.
407
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
407
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
408
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
408
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
409
                        file = NULL;
409
                        file = NULL;
410
                        return(1);
410
                        return(1);
411
                }
411
                }
412
        }
412
        }
413
        return(0);
413
        return(0);
414
}
414
}
415
 
415
 
416
/****************************************************************************************************************************************/
416
/****************************************************************************************************************************************/
417
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
417
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
418
/*                                                                                                                                                                                                                                                                              */
418
/*                                                                                                                                                                                                                                                                              */
419
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
419
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
420
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
420
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
421
/*                                      The subpath is the pointer to the remaining substring of the filepath                                                                                           */
421
/*                                      The subpath is the pointer to the remaining substring of the filepath                                                                                           */
422
/*                                                                                                                                                                                                                                                                              */
422
/*                                                                                                                                                                                                                                                                              */
423
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
423
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
424
/****************************************************************************************************************************************/
424
/****************************************************************************************************************************************/
425
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
425
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
426
{
426
{
427
        s8* subpath = NULL;
427
        s8* subpath = NULL;
428
        u8 readpointer  = 0;
428
        u8 readpointer  = 0;
429
        u8 writepointer = 0;
429
        u8 writepointer = 0;
430
 
430
 
431
        // search subpath from beginning of filepath
431
        // search subpath from beginning of filepath
432
        subpath = NULL;
432
        subpath = NULL;
433
        readpointer     = 0;
433
        readpointer     = 0;
434
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
434
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
435
        while(subpath == NULL)  // search the filepath until a subpath was found.
435
        while(subpath == NULL)  // search the filepath until a subpath was found.
436
        {
436
        {
437
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached
437
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached
438
                {
438
                {
439
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
439
                        subpath = (s8*)&filepath[readpointer];                          // store the position of the first "/" found after the beginning of the filenpath
440
                }
440
                }
441
                readpointer++;
441
                readpointer++;
442
        }
442
        }
443
 
443
 
444
        // clear dirname with spaces
444
        // clear dirname with spaces
445
        dirname[11] = 0; // terminate dirname
445
        dirname[11] = 0; // terminate dirname
446
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
446
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
447
        writepointer = 0;
447
        writepointer = 0;
448
        // start seperating the dirname from the filepath.
448
        // start seperating the dirname from the filepath.
449
        readpointer = 0;
449
        readpointer = 0;
450
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
450
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
451
        while( &filepath[readpointer] < subpath)
451
        while( &filepath[readpointer] < subpath)
452
        {
452
        {
453
                if(writepointer >= 11) return(NULL);            // dirname to long
453
                if(writepointer >= 11) return(NULL);            // dirname to long
454
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
454
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
455
                {
455
                {
456
                        if(writepointer <= 8)
456
                        if(writepointer <= 8)
457
                        {
457
                        {
458
                                readpointer++;                                          // next character in filename
458
                                readpointer++;                                          // next character in filename
459
                                writepointer = 8;                                       // jump to start of extension
459
                                writepointer = 8;                                       // jump to start of extension
460
                        }
460
                        }
461
                        else return(NULL);                                              // dirbasename to long
461
                        else return(NULL);                                              // dirbasename to long
462
                }
462
                }
463
                else
463
                else
464
                {
464
                {
465
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
465
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
466
                        {
466
                        {
467
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
467
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
468
                        }
468
                        }
469
                        else
469
                        else
470
                        {
470
                        {
471
                                dirname[writepointer] = filepath[readpointer];
471
                                dirname[writepointer] = filepath[readpointer];
472
                        }
472
                        }
473
                        readpointer++;
473
                        readpointer++;
474
                        writepointer++;
474
                        writepointer++;
475
                }
475
                }
476
        }
476
        }
477
        return(subpath);
477
        return(subpath);
478
}
478
}
479
 
479
 
480
 
480
 
481
/**************************************************************************************************************************************+*/
481
/**************************************************************************************************************************************+*/
482
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
482
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
483
/*                                                                                                                                                                                                                                                                              */
483
/*                                                                                                                                                                                                                                                                              */
484
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
484
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
485
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
485
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
486
/*                                                                                                                                                                                                                                                                              */
486
/*                                                                                                                                                                                                                                                                              */
487
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
487
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
488
/****************************************************************************************************************************************/
488
/****************************************************************************************************************************************/
489
u32     Fat16ClusterToSector(u16 cluster)
489
u32     Fat16ClusterToSector(u16 cluster)
490
{
490
{
491
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
491
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
492
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
492
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
493
        {
493
        {
494
                return SECTOR_UNDEFINED;
494
                return SECTOR_UNDEFINED;
495
        }
495
        }
496
        else
496
        else
497
        {
497
        {
498
                return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
498
                return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
499
        }
499
        }
500
}
500
}
501
 
501
 
502
/****************************************************************************************************************************************/
502
/****************************************************************************************************************************************/
503
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
503
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
504
/*                                                                                                                                                                                                                                                                              */
504
/*                                                                                                                                                                                                                                                                              */
505
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
505
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
506
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
506
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
507
/*                                                                                                                                                                                                                                                                              */
507
/*                                                                                                                                                                                                                                                                              */
508
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
508
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
509
/****************************************************************************************************************************************/
509
/****************************************************************************************************************************************/
510
u16     SectorToFat16Cluster(u32 sector)
510
u16     SectorToFat16Cluster(u32 sector)
511
{
511
{
512
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
512
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
513
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
513
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
514
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
514
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
515
}
515
}
516
 
516
 
517
 
517
 
518
/****************************************************************************************************************************************/
518
/****************************************************************************************************************************************/
519
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
519
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
520
/*                                                                                                                                                                                                                                                                              */
520
/*                                                                                                                                                                                                                                                                              */
521
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
521
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
522
/*                                                                                                                                                                                                                                                                              */
522
/*                                                                                                                                                                                                                                                                              */
523
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
523
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
524
/****************************************************************************************************************************************/
524
/****************************************************************************************************************************************/
525
u8 Fat16_IsValid(void)
525
u8 Fat16_IsValid(void)
526
{
526
{
527
        return(Partition.IsValid);
527
        return(Partition.IsValid);
528
}
528
}
529
 
529
 
530
/****************************************************************************************************************************************/
530
/****************************************************************************************************************************************/
531
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
531
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
532
/*                                                                                                                                                                                                                                                                              */
532
/*                                                                                                                                                                                                                                                                              */
533
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
533
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
534
/*                                                                                                                                                                                                                                                                              */
534
/*                                                                                                                                                                                                                                                                              */
535
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
535
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
536
/****************************************************************************************************************************************/
536
/****************************************************************************************************************************************/
537
u8 Fat16_Deinit(void)
537
u8 Fat16_Deinit(void)
538
{
538
{
539
        s16 returnvalue = 0;
539
        s16 returnvalue = 0;
540
        u8 cnt;
540
        u8 cnt;
541
 
541
 
542
        UART1_PutString("\r\n FAT16 deinit...");
542
        UART1_PutString("\r\n FAT16 deinit...");
543
        // declare the filepointers as unused.
543
        // declare the filepointers as unused.
544
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
544
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
545
        {
545
        {
546
                if(FilePointer[cnt].State == FSTATE_USED)
546
                if(FilePointer[cnt].State == FSTATE_USED)
547
                {
547
                {
548
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
548
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
549
                }
549
                }
550
                else UnlockFilePointer(&FilePointer[cnt]);
550
                else UnlockFilePointer(&FilePointer[cnt]);
551
 
551
 
552
        }
552
        }
553
        SDC_Deinit();                   // uninitialize interface to sd-card
553
        SDC_Deinit();                   // uninitialize interface to sd-card
554
        Partition.IsValid = 0;  // mark data in partition structure as invalid
554
        Partition.IsValid = 0;  // mark data in partition structure as invalid
555
        Partition.VolumeLabel[0]='\0';
555
        Partition.VolumeLabel[0]='\0';
556
        UART1_PutString("ok");
556
        UART1_PutString("ok");
557
        return(returnvalue);
557
        return(returnvalue);
558
}
558
}
559
 
559
 
560
/****************************************************************************************************************************************/
560
/****************************************************************************************************************************************/
561
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
561
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
562
/*                                                                                                                                                                                                                                                                          */
562
/*                                                                                                                                                                                                                                                                          */
563
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
563
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
564
/*                                      and stores the information in global variables.                                                                                                                                     */
564
/*                                      and stores the information in global variables.                                                                                                                                     */
565
/*                                                                                                                                                                                                                                                                          */
565
/*                                                                                                                                                                                                                                                                          */
566
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
566
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
567
/****************************************************************************************************************************************/
567
/****************************************************************************************************************************************/
568
u8 Fat16_Init(void)
568
u8 Fat16_Init(void)
569
{
569
{
570
    u8  cnt     = 0;
570
    u8  cnt     = 0;
571
        u32     partitionfirstsector;
571
        u32     partitionfirstsector;
572
        VBR_Entry_t *VBR;
572
        VBR_Entry_t *VBR;
573
        MBR_Entry_t *MBR;
573
        MBR_Entry_t *MBR;
574
        File_t *file;
574
        File_t *file;
575
        u8 result = 0;
575
        u8 result = 0;
576
 
576
 
577
        UART1_PutString("\r\n FAT16 init...");
577
        UART1_PutString("\r\n FAT16 init...");
578
        Partition.IsValid = 0;
578
        Partition.IsValid = 0;
579
 
579
 
580
        // declare the filepointers as unused.
580
        // declare the filepointers as unused.
581
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
581
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
582
        {
582
        {
583
                UnlockFilePointer(&FilePointer[cnt]);
583
                UnlockFilePointer(&FilePointer[cnt]);
584
        }
584
        }
585
        // set current file pinter to first position in list
585
        // set current file pinter to first position in list
586
        file = &FilePointer[0];
586
        file = &FilePointer[0];
587
 
587
 
588
        // try to initialize the sd-card.
588
        // try to initialize the sd-card.
589
        if(SD_SUCCESS != SDC_Init())
589
        if(SD_SUCCESS != SDC_Init())
590
        {
590
        {
591
                UART1_PutString("SD-Card could not be initialized.");
591
                UART1_PutString("SD-Card could not be initialized.");
592
                result = 1;
592
                result = 1;
593
                goto end;
593
                goto end;
594
        }
594
        }
595
 
595
 
596
        // SD-Card is initialized successfully
596
        // SD-Card is initialized successfully
597
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
597
        if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache))    // Read the MasterBootRecord
598
        {
598
        {
599
                UART1_PutString("Error reading the MBR.");
599
                UART1_PutString("Error reading the MBR.");
600
                result = 2;
600
                result = 2;
601
                goto end;
601
                goto end;
602
        }
602
        }
603
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
603
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
604
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
604
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
605
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
605
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
606
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
606
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
607
        {
607
        {
608
                // get sector offset 1st partition
608
                // get sector offset 1st partition
609
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
609
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
610
                // Start of Partition is the Volume Boot Sector
610
                // Start of Partition is the Volume Boot Sector
611
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
611
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
612
                {
612
                {
613
                        UART1_PutString("Error reading the VBR.");
613
                        UART1_PutString("Error reading the VBR.");
614
                        result = 3;
614
                        result = 3;
615
                        goto end;
615
                        goto end;
616
                }
616
                }
617
        }
617
        }
618
        else  // maybe the medium has no partition assuming sector 0 is the vbr
618
        else  // maybe the medium has no partition assuming sector 0 is the vbr
619
        {
619
        {
620
                partitionfirstsector = 0;
620
                partitionfirstsector = 0;
621
        }
621
        }
622
 
622
 
623
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
623
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
624
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
624
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
625
        {
625
        {
626
                UART1_PutString("VBR: Sector size not supported.");
626
                UART1_PutString("VBR: Sector size not supported.");
627
                result = 4;
627
                result = 4;
628
                goto end;
628
                goto end;
629
        }
629
        }
630
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
630
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
631
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
631
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
632
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
632
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
633
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT                                // copy volume label
633
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT                                // copy volume label
634
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
634
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
635
 
635
 
636
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
636
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
637
        // Calculate the position of the FileAllocationTable:
637
        // Calculate the position of the FileAllocationTable:
638
        // Start + # of Reserved Sectors
638
        // Start + # of Reserved Sectors
639
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
639
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
640
        // Calculate the position of the Rootdirectory:
640
        // Calculate the position of the Rootdirectory:
641
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
641
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
642
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
642
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
643
        // Calculate the position of the first datacluster:
643
        // Calculate the position of the first datacluster:
644
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
644
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
645
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
645
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (u32)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
646
        // Calculate the last data sector
646
        // Calculate the last data sector
647
        if(VBR->NoSectors == 0)
647
        if(VBR->NoSectors == 0)
648
        {
648
        {
649
                UART1_PutString("VBR: Bad number of sectors.");
649
                UART1_PutString("VBR: Bad number of sectors.");
650
                result = 5;
650
                result = 5;
651
                goto end;
651
                goto end;
652
        }
652
        }
653
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
653
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
654
        // check for FAT16 in VBR of first partition
654
        // check for FAT16 in VBR of first partition
655
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
655
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
656
        {
656
        {
657
                UART1_PutString("VBR: Partition ist not FAT16 type.");
657
                UART1_PutString("VBR: Partition ist not FAT16 type.");
658
                result = 6;
658
                result = 6;
659
                goto end;
659
                goto end;
660
        }
660
        }
661
        Partition.IsValid = 1; // mark data in partition structure as valid
661
        Partition.IsValid = 1; // mark data in partition structure as valid
662
        result = 0;
662
        result = 0;
663
        end:
663
        end:
664
        if(result != 0) Fat16_Deinit();
664
        if(result != 0) Fat16_Deinit();
665
        else UART1_PutString("ok");
665
        else UART1_PutString("ok");
666
        return(result);
666
        return(result);
667
}
667
}
668
 
668
 
669
 
669
 
670
 
670
 
671
/****************************************************************************************************************************************/
671
/****************************************************************************************************************************************/
672
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
672
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
673
/*                                                                                                                                                                                                                                                                              */
673
/*                                                                                                                                                                                                                                                                              */
674
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
674
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
675
/*                                                                                                                                                                                                                                                                              */
675
/*                                                                                                                                                                                                                                                                              */
676
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
676
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
677
/****************************************************************************************************************************************/
677
/****************************************************************************************************************************************/
678
u8 ClearCurrCluster(File_t * file)
678
u8 ClearCurrCluster(File_t * file)
679
{
679
{
680
        u8 retvalue = 1;
680
        u8 retvalue = 1;
681
        u32 i;
681
        u32 i;
682
 
682
 
683
        if((!Partition.IsValid) || (file == NULL)) return(0);
683
        if((!Partition.IsValid) || (file == NULL)) return(0);
684
 
684
 
685
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
685
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
686
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do 
686
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do 
687
        for(i = 0; i < Partition.SectorsPerCluster; i++)
687
        for(i = 0; i < Partition.SectorsPerCluster; i++)
688
        {
688
        {
689
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
689
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
690
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
690
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
691
                {
691
                {
692
                        Fat16_Deinit();
692
                        Fat16_Deinit();
693
                        retvalue = 0;
693
                        retvalue = 0;
-
 
694
                        return(retvalue);
694
                }
695
                }
695
        }
696
        }
696
        return(retvalue);
697
        return(retvalue);
697
}
698
}
698
 
699
 
699
/*****************************************************************************************************************************************/
700
/*****************************************************************************************************************************************/
700
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
701
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
701
/*                                                                                                                                                                                                                                                                               */
702
/*                                                                                                                                                                                                                                                                               */
702
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
703
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
703
/*                                                                                                                                                                                                                                                                               */
704
/*                                                                                                                                                                                                                                                                               */
704
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
705
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
705
/*****************************************************************************************************************************************/
706
/*****************************************************************************************************************************************/
706
u16 GetNextCluster(File_t * file)
707
u16 GetNextCluster(File_t * file)
707
{
708
{
708
        u16 cluster = CLUSTER_UNDEFINED;
709
        u16 cluster = CLUSTER_UNDEFINED;
709
        u32 fat_byte_offset, sector, byte;
710
        u32 fat_byte_offset, sector, byte;
710
        Fat16Entry_t * fat;
711
        Fat16Entry_t * fat;
711
 
712
 
712
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
713
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
713
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
714
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
714
        // if sector is within the data area
715
        // if sector is within the data area
715
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
716
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
716
        {
717
        {
717
                // determine current file cluster
718
                // determine current file cluster
718
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
719
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
719
                // calculate byte offset in the fat for corresponding entry
720
                // calculate byte offset in the fat for corresponding entry
720
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
721
                fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
721
                // calculate the sector that contains the current cluster within the fat
722
                // calculate the sector that contains the current cluster within the fat
722
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
723
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
723
                // calculate byte offset of the current cluster within that fat sector
724
                // calculate byte offset of the current cluster within that fat sector
724
                byte = fat_byte_offset % BYTES_PER_SECTOR;
725
                byte = fat_byte_offset % BYTES_PER_SECTOR;
725
                // read this sector to the file cache
726
                // read this sector to the file cache
726
                if(file->SectorInCache != sector)
727
                if(file->SectorInCache != sector)
727
                {
728
                {
728
                        file->SectorInCache = sector;                                           // update sector stored in buffer
729
                        file->SectorInCache = sector;                                           // update sector stored in buffer
729
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
730
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
730
                        {
731
                        {
731
                                Fat16_Deinit();
732
                                Fat16_Deinit();
732
                                return (cluster);
733
                                return (cluster);
733
                        }
734
                        }
734
                }
735
                }
735
                // read the next cluster from cache
736
                // read the next cluster from cache
736
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
737
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
737
                cluster = fat->NextCluster;
738
                cluster = fat->NextCluster;
738
                // if no next cluster exist
739
                // if no next cluster exist
739
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
740
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
740
                {
741
                {
741
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
742
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
742
                }
743
                }
743
                else
744
                else
744
                {
745
                {
745
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
746
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
746
                        file->SectorOfCurrCluster = 0;
747
                        file->SectorOfCurrCluster = 0;
747
                        file->ByteOfCurrSector = 0;
748
                        file->ByteOfCurrSector = 0;
748
                }
749
                }
749
        }
750
        }
750
        return(cluster);
751
        return(cluster);
751
}
752
}
752
 
753
 
753
 
754
 
754
/****************************************************************************************************************************************/
755
/****************************************************************************************************************************************/
755
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
756
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
756
/*                                                                                                                                                                                                                                                                              */
757
/*                                                                                                                                                                                                                                                                              */
757
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
758
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
758
/*                                                                                                                                                                                                                                                                              */
759
/*                                                                                                                                                                                                                                                                              */
759
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
760
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
760
/****************************************************************************************************************************************/
761
/****************************************************************************************************************************************/
761
u16 FindNextFreeCluster(File_t *file)
762
u16 FindNextFreeCluster(File_t *file)
762
{
763
{
763
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
764
        u32 fat_sector;                                 // current sector within the fat relative to the first sector of the fat.
764
        u32     curr_sector;                            // current sector
765
        u32     curr_sector;                            // current sector
765
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
766
        u16     fat_entry;                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
766
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
767
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
767
        Fat16Entry_t * fat;
768
        Fat16Entry_t * fat;
768
 
769
 
769
        if((!Partition.IsValid) || (file == NULL)) return(0);
770
        if((!Partition.IsValid) || (file == NULL)) return(0);
770
 
771
 
771
        // start searching for an empty cluster at the beginning of the fat.
772
        // start searching for an empty cluster at the beginning of the fat.
772
        fat_sector = 0;
773
        fat_sector = 0;
773
        do
774
        do
774
        {
775
        {
775
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
776
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
776
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
777
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
777
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
778
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
778
                {
779
                {
779
                        Fat16_Deinit();
780
                        Fat16_Deinit();
780
                        return(free_cluster);
781
                        return(free_cluster);
781
                }
782
                }
782
 
783
 
783
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
784
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
784
 
785
 
785
                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.
786
                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.
786
                {
787
                {
787
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
788
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
788
                        {
789
                        {
789
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
790
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
790
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
791
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
791
                                {
792
                                {
792
                                        Fat16_Deinit();
793
                                        Fat16_Deinit();
793
                                        return(free_cluster);
794
                                        return(free_cluster);
794
                                }
795
                                }
795
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
796
                                free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry);
796
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
797
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
797
                        }
798
                        }
798
                }
799
                }
799
                fat_sector++;                                                                                                   // continue the search in next fat sector
800
                fat_sector++;                                                                                                   // continue the search in next fat sector
800
        // repeat until the end of the fat is  reached and no free cluster has been found so far
801
        // repeat until the end of the fat is  reached and no free cluster has been found so far
801
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
802
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
802
        return(free_cluster);
803
        return(free_cluster);
803
}
804
}
804
 
805
 
805
 
806
 
806
/****************************************************************************************************************************************************/
807
/****************************************************************************************************************************************************/
807
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
808
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
808
/*                                                                                                                                                                                                                                                                                                      */
809
/*                                                                                                                                                                                                                                                                                                      */
809
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
810
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
810
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
811
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
811
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                                                                     */
812
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                                                                     */
812
/****************************************************************************************************************************************************/
813
/****************************************************************************************************************************************************/
813
s16 fseek_(File_t *file, s32 offset, s16 origin)
814
s16 fseek_(File_t *file, s32 offset, s16 origin)
814
{
815
{
815
        s32             fposition       = 0;
816
        s32             fposition       = 0;
816
        s16     retvalue        = 1;
817
        s16     retvalue        = 1;
817
 
818
 
818
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
819
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
819
        switch(origin)
820
        switch(origin)
820
        {
821
        {
821
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
822
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
822
                        fposition = 0;
823
                        fposition = 0;
823
                        break;
824
                        break;
824
                case SEEK_END:                          // Fileposition relative to the end of the file.
825
                case SEEK_END:                          // Fileposition relative to the end of the file.
825
                        fposition = (s32)file->Size;
826
                        fposition = (s32)file->Size;
826
                        break;
827
                        break;
827
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
828
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
828
                default:
829
                default:
829
                        fposition = file->Position;
830
                        fposition = file->Position;
830
                        break;
831
                        break;
831
        }
832
        }
832
 
833
 
833
        fposition += offset;
834
        fposition += offset;
834
 
835
 
835
        if((fposition >= 0) && (fposition <= (s32)file->Size))          // is the pointer still within the file?
836
        if((fposition >= 0) && (fposition <= (s32)file->Size))          // is the pointer still within the file?
836
        {
837
        {
837
                // reset file position to start of the file
838
                // reset file position to start of the file
838
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
839
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
839
                file->SectorOfCurrCluster       = 0;
840
                file->SectorOfCurrCluster       = 0;
840
                file->ByteOfCurrSector          = 0;
841
                file->ByteOfCurrSector          = 0;
841
                file->Position                          = 0;
842
                file->Position                          = 0;
842
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
843
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
843
                while(file->Position < fposition)       // repeat until the current position is less than target
844
                while(file->Position < fposition)       // repeat until the current position is less than target
844
                {
845
                {
845
                        file->Position++;                               // increment file position
846
                        file->Position++;                               // increment file position
846
                        file->ByteOfCurrSector++;               // next byte in current sector
847
                        file->ByteOfCurrSector++;               // next byte in current sector
847
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
848
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
848
                        {
849
                        {
849
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
850
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
850
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
851
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
851
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
852
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
852
                                {
853
                                {
853
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
854
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
854
                                        {
855
                                        {
855
                                                file->SectorOfCurrCluster = 0;
856
                                                file->SectorOfCurrCluster = 0;
856
                                        }
857
                                        }
857
                                        else // the last cluster was allready reached
858
                                        else // the last cluster was allready reached
858
                                        {
859
                                        {
859
                                                file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
860
                                                file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
860
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
861
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
861
                                        }
862
                                        }
862
                                }
863
                                }
863
                        }
864
                        }
864
                }
865
                }
865
        }
866
        }
866
        if(file->Position == fposition) retvalue = 0;
867
        if(file->Position == fposition) retvalue = 0;
867
        return(retvalue);
868
        return(retvalue);
868
}
869
}
869
 
870
 
870
 
871
 
871
/****************************************************************************************************************************************/
872
/****************************************************************************************************************************************/
872
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
873
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
873
/*                                                                                                                                                                                                                                                                              */
874
/*                                                                                                                                                                                                                                                                              */
874
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
875
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
875
/*                                                                                                                                                                                                                                                                              */
876
/*                                                                                                                                                                                                                                                                              */
876
/****************************************************************************************************************************************/
877
/****************************************************************************************************************************************/
877
u8 DeleteClusterChain(u16 StartCluster)
878
u8 DeleteClusterChain(u16 StartCluster)
878
{
879
{
879
        u16 cluster;
880
        u16 cluster;
880
        u32 fat_byte_offset, sector, byte;
881
        u32 fat_byte_offset, sector, byte;
881
        Fat16Entry_t * fat;
882
        Fat16Entry_t * fat;
882
        u8 buffer[BYTES_PER_SECTOR];
883
        u8 buffer[BYTES_PER_SECTOR];
883
        u32 sector_in_buffer = 0;
884
        u32 sector_in_buffer = 0;
884
        u8 repeat = 0;
885
        u8 repeat = 0;
885
 
886
 
886
        if(!Partition.IsValid) return(0);
887
        if(!Partition.IsValid) return(0);
887
        if(StartCluster == CLUSTER_UNDEFINED) return(0);
888
        if(StartCluster == CLUSTER_UNDEFINED) return(0);
888
        cluster = StartCluster; // init chain trace
889
        cluster = StartCluster; // init chain trace
889
        // if start cluster is no real cluster
890
        // if start cluster is no real cluster
890
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1;
891
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1;
891
 
892
 
892
        // calculate byte offset in the fat for corresponding entry
893
        // calculate byte offset in the fat for corresponding entry
893
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
894
        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
894
        // calculate the sector that contains the current cluster within the fat
895
        // calculate the sector that contains the current cluster within the fat
895
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
896
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
896
        // calculate byte offset of the current cluster within that fat sector
897
        // calculate byte offset of the current cluster within that fat sector
897
        byte = fat_byte_offset % BYTES_PER_SECTOR;
898
        byte = fat_byte_offset % BYTES_PER_SECTOR;
898
        do
899
        do
899
        {
900
        {
900
                if(sector != sector_in_buffer)
901
                if(sector != sector_in_buffer)
901
                {
902
                {
902
                        // read this sector to buffer
903
                        // read this sector to buffer
903
                        sector_in_buffer = sector;
904
                        sector_in_buffer = sector;
904
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
905
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
905
                }
906
                }
906
                // read the next cluster from cache
907
                // read the next cluster from cache
907
                fat = (Fat16Entry_t *)(&(buffer[byte]));
908
                fat = (Fat16Entry_t *)(&(buffer[byte]));
908
                cluster = fat->NextCluster;
909
                cluster = fat->NextCluster;
909
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
910
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
910
 
911
 
911
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
912
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
912
                {
913
                {
913
                        repeat = 1;
914
                        repeat = 1;
914
                        // calculate sector byte and byte offset in the fat for the next cluster
915
                        // calculate sector byte and byte offset in the fat for the next cluster
915
                        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
916
                        fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
916
                        // calculate the sector that contains the current cluster within the fat
917
                        // calculate the sector that contains the current cluster within the fat
917
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
918
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
918
                        // calculate byte offset of the current cluster within that fat sector
919
                        // calculate byte offset of the current cluster within that fat sector
919
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
920
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
920
                }
921
                }
921
                else repeat = 0;
922
                else repeat = 0;
922
 
923
 
923
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
924
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
924
                if((sector != sector_in_buffer) || !repeat)
925
                if((sector != sector_in_buffer) || !repeat)
925
                {       // write sector in buffer
926
                {       // write sector in buffer
926
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
927
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
927
                        {
928
                        {
928
                                Fat16_Deinit();
929
                                Fat16_Deinit();
929
                                return(0);
930
                                return(0);
930
                        }
931
                        }
931
                }
932
                }
932
        }
933
        }
933
        while(repeat);
934
        while(repeat);
934
 
935
 
935
        return 1;
936
        return 1;
936
}
937
}
937
 
938
 
938
 
939
 
939
/****************************************************************************************************************************************/
940
/****************************************************************************************************************************************/
940
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
941
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
941
/*                                                                                                                                                                                                                                                                              */
942
/*                                                                                                                                                                                                                                                                              */
942
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
943
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
943
/*                                                                                                                                                                                                                                                                              */
944
/*                                                                                                                                                                                                                                                                              */
944
/* Returnvalue: The function returns the appened cluster number or CLUSTER_UNDEFINED of no cluster was appended.                                                */
945
/* Returnvalue: The function returns the appened cluster number or CLUSTER_UNDEFINED of no cluster was appended.                                                */
945
/****************************************************************************************************************************************/
946
/****************************************************************************************************************************************/
946
u16 AppendCluster(File_t *file)
947
u16 AppendCluster(File_t *file)
947
{
948
{
948
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
949
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
949
        u32 fat_byte_offset, sector, byte;
950
        u32 fat_byte_offset, sector, byte;
950
        Fat16Entry_t * fat;
951
        Fat16Entry_t * fat;
951
 
952
 
952
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
953
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
953
 
954
 
954
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
955
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
955
        if(new_cluster != CLUSTER_UNDEFINED)
956
        if(new_cluster != CLUSTER_UNDEFINED)
956
        {       // A free cluster was found and can be added to the end of the file.
957
        {       // A free cluster was found and can be added to the end of the file.
957
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
958
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
958
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
959
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
959
                if(last_cluster != CLUSTER_UNDEFINED)
960
                if(last_cluster != CLUSTER_UNDEFINED)
960
                {
961
                {
961
                        // update FAT entry of last cluster
962
                        // update FAT entry of last cluster
962
                        fat_byte_offset = ((u32)last_cluster)<<1;
963
                        fat_byte_offset = ((u32)last_cluster)<<1;
963
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
964
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
964
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
965
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
965
                        // read the sector containing the last cluster of the file
966
                        // read the sector containing the last cluster of the file
966
                        if(file->SectorInCache != sector)
967
                        if(file->SectorInCache != sector)
967
                        {
968
                        {
968
                                file->SectorInCache = sector;   // update sector stored in buffer
969
                                file->SectorInCache = sector;   // update sector stored in buffer
969
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
970
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
970
                                {
971
                                {
971
                                        Fat16_Deinit();
972
                                        Fat16_Deinit();
972
                                        return(0);
973
                                        return(0);
973
                                }
974
                                }
974
                        }
975
                        }
975
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
976
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
976
                        fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
977
                        fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
977
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
978
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
978
                        {
979
                        {
979
                                Fat16_Deinit();
980
                                Fat16_Deinit();
980
                                return(0);
981
                                return(0);
981
                        }
982
                        }
982
                }
983
                }
983
                else // last cluster of the file is undefined
984
                else // last cluster of the file is undefined
984
                {   // then the new cluster must be the first one of the file
985
                {   // then the new cluster must be the first one of the file
985
                    // and its cluster number must be set in the direntry
986
                    // and its cluster number must be set in the direntry
986
                        DirEntry_t * dir;
987
                        DirEntry_t * dir;
987
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
988
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
988
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
989
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
989
                        {
990
                        {
990
                                Fat16_Deinit();
991
                                Fat16_Deinit();
991
                                return(CLUSTER_UNDEFINED);
992
                                return(CLUSTER_UNDEFINED);
992
                        }
993
                        }
993
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
994
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
994
                        dir[file->DirectoryIndex].Res1 = 0;
995
                        dir[file->DirectoryIndex].Res1 = 0;
995
                        dir[file->DirectoryIndex].Res2[0] = 0;
996
                        dir[file->DirectoryIndex].Res2[0] = 0;
996
                        dir[file->DirectoryIndex].Res2[1] = 0;
997
                        dir[file->DirectoryIndex].Res2[1] = 0;
997
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster 
998
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster 
998
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
999
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
999
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1000
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1000
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1001
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1001
                        dir[file->DirectoryIndex].Size          = 0;
1002
                        dir[file->DirectoryIndex].Size          = 0;
1002
                        // write sector containing the direntry
1003
                        // write sector containing the direntry
1003
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1004
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1004
                        {
1005
                        {
1005
                                Fat16_Deinit();
1006
                                Fat16_Deinit();
1006
                                return(CLUSTER_UNDEFINED);
1007
                                return(CLUSTER_UNDEFINED);
1007
                        }
1008
                        }
1008
                        // update file info     
1009
                        // update file info     
1009
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1010
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1010
                        file->Size = 0;
1011
                        file->Size = 0;
1011
                        file->Position = 0;
1012
                        file->Position = 0;
1012
                }
1013
                }
1013
                // update file pointes
1014
                // update file pointes
1014
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1015
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1015
                file->SectorOfCurrCluster = 0;
1016
                file->SectorOfCurrCluster = 0;
1016
                file->ByteOfCurrSector = 0;
1017
                file->ByteOfCurrSector = 0;
1017
        }
1018
        }
1018
        return(new_cluster);
1019
        return(new_cluster);
1019
}
1020
}
1020
 
1021
 
1021
/****************************************************************************************************************************************************/
1022
/****************************************************************************************************************************************************/
1022
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1023
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1023
/*                                                                                                                                                                                                                                                                                                      */
1024
/*                                                                                                                                                                                                                                                                                                      */
1024
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
1025
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
1025
/*                                                                                                                                                                                                                                                                                                      */
1026
/*                                                                                                                                                                                                                                                                                                      */
1026
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
1027
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
1027
/****************************************************************************************************************************************************/
1028
/****************************************************************************************************************************************************/
1028
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1029
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1029
{
1030
{
1030
        u32             dir_sector, max_dir_sector, curr_sector;
1031
        u32             dir_sector, max_dir_sector, curr_sector;
1031
        u16     dir_entry = 0;
1032
        u16     dir_entry = 0;
1032
 
1033
 
1033
        u16     end_of_directory_not_reached = 0;
1034
        u16     end_of_directory_not_reached = 0;
1034
        u8              i = 0;
1035
        u8              i = 0;
1035
        u8      direntry_exist = 0;
1036
        u8      direntry_exist = 0;
1036
        DirEntry_t * dir;
1037
        DirEntry_t * dir;
1037
 
1038
 
1038
        // if incomming pointers are useless return immediatly
1039
        // if incomming pointers are useless return immediatly
1039
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1040
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1040
 
1041
 
1041
        // dir entries can be searched only in filesclusters that have
1042
        // dir entries can be searched only in filesclusters that have
1042
        // a corresponding dir entry with adir-flag set in its attribute
1043
        // a corresponding dir entry with adir-flag set in its attribute
1043
        // or direct within the root directory area
1044
        // or direct within the root directory area
1044
 
1045
 
1045
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1046
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1046
        // no current directory exist therefore assume searching in the root
1047
        // no current directory exist therefore assume searching in the root
1047
        if(file->DirectorySector == SECTOR_UNDEFINED)
1048
        if(file->DirectorySector == SECTOR_UNDEFINED)
1048
        {
1049
        {
1049
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1050
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1050
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1051
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1051
        }
1052
        }
1052
        // within the root directory area we can read sectors sequentially until the end of this area
1053
        // within the root directory area we can read sectors sequentially until the end of this area
1053
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1054
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1054
        {
1055
        {
1055
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1056
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1056
        }
1057
        }
1057
        // within the data clusters we can read sectors sequentially only within the cluster
1058
        // within the data clusters we can read sectors sequentially only within the cluster
1058
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1059
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1059
        {
1060
        {
1060
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
1061
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
1061
        }
1062
        }
1062
        else return (direntry_exist); // bad sector range for directory sector of the file
1063
        else return (direntry_exist); // bad sector range for directory sector of the file
1063
        // if search area is not defined yet
1064
        // if search area is not defined yet
1064
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1065
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1065
        {
1066
        {
1066
                // check if the directory entry of current file is existent and has the dir-flag set
1067
                // check if the directory entry of current file is existent and has the dir-flag set
1067
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1068
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1068
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1069
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1069
                {
1070
                {
1070
                        Fat16_Deinit();
1071
                        Fat16_Deinit();
1071
                        return(direntry_exist);
1072
                        return(direntry_exist);
1072
                }
1073
                }
1073
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1074
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1074
                switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1075
                switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1075
                {
1076
                {
1076
                        case SLOT_EMPTY:
1077
                        case SLOT_EMPTY:
1077
                        case SLOT_DELETED:
1078
                        case SLOT_DELETED:
1078
                                // the directrory pointer of this file points to a deleted or not existen directory
1079
                                // the directrory pointer of this file points to a deleted or not existen directory
1079
                                // therefore no file or subdirectory can be created
1080
                                // therefore no file or subdirectory can be created
1080
                                return (direntry_exist);
1081
                                return (direntry_exist);
1081
                                break;
1082
                                break;
1082
                        default:        // and is a real directory
1083
                        default:        // and is a real directory
1083
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1084
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1084
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1085
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1085
                                        return (direntry_exist);
1086
                                        return (direntry_exist);
1086
                                }
1087
                                }
1087
                                break;
1088
                                break;
1088
                }
1089
                }
1089
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
1090
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
1090
        }
1091
        }
1091
 
1092
 
1092
        // update current file data area position to start of first cluster
1093
        // update current file data area position to start of first cluster
1093
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1094
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1094
        file->SectorOfCurrCluster               = 0;
1095
        file->SectorOfCurrCluster               = 0;
1095
        file->ByteOfCurrSector                  = 0;
1096
        file->ByteOfCurrSector                  = 0;
1096
 
1097
 
1097
        do // loop over all data clusters of the current directory entry
1098
        do // loop over all data clusters of the current directory entry
1098
        {
1099
        {
1099
                dir_sector = 0; // reset sector counter within a new cluster
1100
                dir_sector = 0; // reset sector counter within a new cluster
1100
                do // loop over all sectors of a cluster or all sectors of the root directory
1101
                do // loop over all sectors of a cluster or all sectors of the root directory
1101
                {
1102
                {
1102
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1103
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1103
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1104
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1104
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1105
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
1105
                        {
1106
                        {
1106
                                Fat16_Deinit();
1107
                                Fat16_Deinit();
1107
                                return(direntry_exist);
1108
                                return(direntry_exist);
1108
                        }
1109
                        }
1109
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1110
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1110
                        // search all directory entries within that sector
1111
                        // search all directory entries within that sector
1111
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1112
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1112
                        {   // check for existing dir entry
1113
                        {   // check for existing dir entry
1113
                                switch((u8)dir[dir_entry].Name[0])
1114
                                switch((u8)dir[dir_entry].Name[0])
1114
                                {
1115
                                {
1115
                                        case SLOT_EMPTY:
1116
                                        case SLOT_EMPTY:
1116
                                        case SLOT_DELETED:
1117
                                        case SLOT_DELETED:
1117
                                                // ignore empty or deleted dir entries
1118
                                                // ignore empty or deleted dir entries
1118
                                                break;
1119
                                                break;
1119
                                        default:
1120
                                        default:
1120
                                                // if existing check attributes before names are compared will safe performance
1121
                                                // if existing check attributes before names are compared will safe performance
1121
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1122
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1122
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
1123
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
1123
                                                i = 0;
1124
                                                i = 0;
1124
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1125
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1125
                                                if (i < 10) break; // names does not match
1126
                                                if (i < 10) break; // names does not match
1126
                                                // if dirname and attribute have matched
1127
                                                // if dirname and attribute have matched
1127
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
1128
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
1128
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
1129
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
1129
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1130
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1130
                                                file->SectorOfCurrCluster = 0;
1131
                                                file->SectorOfCurrCluster = 0;
1131
                                                file->ByteOfCurrSector = 0;
1132
                                                file->ByteOfCurrSector = 0;
1132
                                                file->DirectorySector = curr_sector; // current sector
1133
                                                file->DirectorySector = curr_sector; // current sector
1133
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1134
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1134
                                                file->Size = dir[dir_entry].Size;
1135
                                                file->Size = dir[dir_entry].Size;
1135
                                                direntry_exist = 1; // mark as found
1136
                                                direntry_exist = 1; // mark as found
1136
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1137
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1137
                                } // end of first byte of name check
1138
                                } // end of first byte of name check
1138
                        }
1139
                        }
1139
                        dir_sector++; // search next sector
1140
                        dir_sector++; // search next sector
1140
                // stop if we reached the end of the cluster or the end of the root dir
1141
                // stop if we reached the end of the cluster or the end of the root dir
1141
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1142
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1142
 
1143
 
1143
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1144
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1144
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1145
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1145
                {
1146
                {
1146
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1147
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1147
                }
1148
                }
1148
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
1149
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
1149
        return(direntry_exist);
1150
        return(direntry_exist);
1150
}
1151
}
1151
 
1152
 
1152
 
1153
 
1153
/****************************************************************************************************************************************/
1154
/****************************************************************************************************************************************/
1154
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1155
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1155
/*                                                                                                                                                                                                                                                                              */
1156
/*                                                                                                                                                                                                                                                                              */
1156
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
1157
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
1157
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
1158
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
1158
/*                                                                                                                                                                                                                                                                              */
1159
/*                                                                                                                                                                                                                                                                              */
1159
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1160
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1160
/****************************************************************************************************************************************/
1161
/****************************************************************************************************************************************/
1161
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1162
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1162
{
1163
{
1163
        u32 dir_sector, max_dir_sector, curr_sector;
1164
        u32 dir_sector, max_dir_sector, curr_sector;
1164
        u16 dir_entry   = 0;
1165
        u16 dir_entry   = 0;
1165
        u16 subdircluster, dircluster = 0;
1166
        u16 subdircluster, dircluster = 0;
1166
        u16 end_of_directory_not_reached = 0;
1167
        u16 end_of_directory_not_reached = 0;
1167
        u8      i                       = 0;
1168
        u8      i                       = 0;
1168
        u8      retvalue        = 0;
1169
        u8      retvalue        = 0;
1169
        DirEntry_t *dir;
1170
        DirEntry_t *dir;
1170
 
1171
 
1171
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
1172
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
1172
        // It is not checked here that the dir entry that should be created is already existent!
1173
        // It is not checked here that the dir entry that should be created is already existent!
1173
 
1174
 
1174
        // Dir entries can be created only in file-clusters that have
1175
        // Dir entries can be created only in file-clusters that have
1175
        // the dir-flag set in its attribute or within the root directory
1176
        // the dir-flag set in its attribute or within the root directory
1176
 
1177
 
1177
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1178
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1178
        // no current directory exist therefore assume creating in the root
1179
        // no current directory exist therefore assume creating in the root
1179
        if(file->DirectorySector == SECTOR_UNDEFINED)
1180
        if(file->DirectorySector == SECTOR_UNDEFINED)
1180
        {
1181
        {
1181
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1182
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1182
                dircluster = 0;
1183
                dircluster = 0;
1183
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1184
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1184
        }
1185
        }
1185
        // within the root directory area we can read sectors sequentially until the end of this area
1186
        // within the root directory area we can read sectors sequentially until the end of this area
1186
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1187
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1187
        {
1188
        {
1188
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1189
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1189
        }
1190
        }
1190
        // within the data clusters we can read sectors sequentially only within the cluster
1191
        // within the data clusters we can read sectors sequentially only within the cluster
1191
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1192
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1192
        {
1193
        {
1193
                max_dir_sector = Partition.SectorsPerCluster;
1194
                max_dir_sector = Partition.SectorsPerCluster;
1194
        }
1195
        }
1195
        else return (retvalue); // bad sector range for directory sector of the file
1196
        else return (retvalue); // bad sector range for directory sector of the file
1196
        // if search area is not defined yet
1197
        // if search area is not defined yet
1197
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1198
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1198
        {
1199
        {
1199
            // check if the directory entry of current file is existent and has the dir-flag set
1200
            // check if the directory entry of current file is existent and has the dir-flag set
1200
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1201
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1201
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1202
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1202
                {
1203
                {
1203
                        Fat16_Deinit();
1204
                        Fat16_Deinit();
1204
                        return(retvalue);
1205
                        return(retvalue);
1205
                }
1206
                }
1206
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1207
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1207
                switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1208
                switch((u8)dir[file->DirectoryIndex].Name[0])                           // check if current directory exist
1208
                {
1209
                {
1209
                        case SLOT_EMPTY:
1210
                        case SLOT_EMPTY:
1210
                        case SLOT_DELETED:
1211
                        case SLOT_DELETED:
1211
                                return (retvalue);
1212
                                return (retvalue);
1212
                                break;
1213
                                break;
1213
                        default:        // and is a real directory
1214
                        default:        // and is a real directory
1214
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1215
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1215
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1216
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1216
                                        return (retvalue);
1217
                                        return (retvalue);
1217
                                }
1218
                                }
1218
                                break;
1219
                                break;
1219
                }
1220
                }
1220
                dircluster = dir[file->DirectoryIndex].StartCluster;
1221
                dircluster = dir[file->DirectoryIndex].StartCluster;
1221
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1222
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1222
        }
1223
        }
1223
 
1224
 
1224
        // if the new direntry is a subdirectory
1225
        // if the new direntry is a subdirectory
1225
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1226
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1226
        {       // get a free clutser for its content
1227
        {       // get a free clutser for its content
1227
                subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1228
                subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1228
        }
1229
        }
1229
        else // a normal file
1230
        else // a normal file
1230
        {       // has no data cluster after creation
1231
        {       // has no data cluster after creation
1231
                subdircluster = CLUSTER_UNDEFINED;
1232
                subdircluster = CLUSTER_UNDEFINED;
1232
        }
1233
        }
1233
 
1234
 
1234
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1235
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1235
        file->SectorOfCurrCluster               = 0;
1236
        file->SectorOfCurrCluster               = 0;
1236
        do // loop over all clusters of current directory
1237
        do // loop over all clusters of current directory
1237
        {
1238
        {
1238
                dir_sector = 0; // reset sector counter within a new cluster
1239
                dir_sector = 0; // reset sector counter within a new cluster
1239
                do // loop over all sectors of a cluster or all sectors of the root directory
1240
                do // loop over all sectors of a cluster or all sectors of the root directory
1240
                {
1241
                {
1241
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1242
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1242
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1243
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1243
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1244
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1244
                        {
1245
                        {
1245
                                Fat16_Deinit();
1246
                                Fat16_Deinit();
1246
                                return(retvalue);
1247
                                return(retvalue);
1247
                        }
1248
                        }
1248
 
1249
 
1249
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1250
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1250
                        // search all directory entries of a sector
1251
                        // search all directory entries of a sector
1251
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1252
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1252
                        {       // check if current direntry is available
1253
                        {       // check if current direntry is available
1253
                                if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1254
                                if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
1254
                                {       // a free direntry was found
1255
                                {       // a free direntry was found
1255
                                        for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1256
                                        for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1256
                                        dir[dir_entry].Attribute    = attrib;
1257
                                        dir[dir_entry].Attribute    = attrib;
1257
                                        dir[dir_entry].Res1 = 0;
1258
                                        dir[dir_entry].Res1 = 0;
1258
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1259
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1259
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1260
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1260
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1261
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1261
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1262
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1262
                                        dir[dir_entry].Res2[0] = 0;
1263
                                        dir[dir_entry].Res2[0] = 0;
1263
                                        dir[dir_entry].Res2[1] = 0;
1264
                                        dir[dir_entry].Res2[1] = 0;
1264
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1265
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1265
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1266
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1266
                                        // Set the attribute of the new directoryentry.
1267
                                        // Set the attribute of the new directoryentry.
1267
                                        dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1268
                                        dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1268
                                        dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1269
                                        dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1269
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1270
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1270
                                        {
1271
                                        {
1271
                                                Fat16_Deinit();
1272
                                                Fat16_Deinit();
1272
                                                return(retvalue);
1273
                                                return(retvalue);
1273
                                        }
1274
                                        }
1274
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1275
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1275
                                        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1276
                                        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1276
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1277
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1277
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1278
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1278
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1279
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1279
                                        file->Size                                              = 0;                                                        // new file has no size
1280
                                        file->Size                                              = 0;                                                        // new file has no size
1280
                                        file->DirectorySector                   = curr_sector;
1281
                                        file->DirectorySector                   = curr_sector;
1281
                                        file->DirectoryIndex                    = dir_entry;
1282
                                        file->DirectoryIndex                    = dir_entry;
1282
                                        // prepare subdirectory data cluster
1283
                                        // prepare subdirectory data cluster
1283
                                        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1284
                                        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1284
                                        {
1285
                                        {
1285
                                                ClearCurrCluster(file); // fill cluster with zeros
1286
                                                ClearCurrCluster(file); // fill cluster with zeros
1286
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1287
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1287
                                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1288
                                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1288
                                                {
1289
                                                {
1289
                                                        Fat16_Deinit();
1290
                                                        Fat16_Deinit();
1290
                                                        return(retvalue);
1291
                                                        return(retvalue);
1291
                                                }
1292
                                                }
1292
                                                dir = (DirEntry_t *)file->Cache;
1293
                                                dir = (DirEntry_t *)file->Cache;
1293
                                                // create direntry "." to current dir
1294
                                                // create direntry "." to current dir
1294
                                                dir[0].Name[0] = 0x2E;
1295
                                                dir[0].Name[0] = 0x2E;
1295
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1296
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1296
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1297
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1297
                                                dir[0].StartCluster = subdircluster;
1298
                                                dir[0].StartCluster = subdircluster;
1298
                                                dir[0].Size = 0;
1299
                                                dir[0].Size = 0;
1299
                                                // create direntry ".." to the upper dir
1300
                                                // create direntry ".." to the upper dir
1300
                                                dir[1].Name[0] = 0x2E;
1301
                                                dir[1].Name[0] = 0x2E;
1301
                                                dir[1].Name[1] = 0x2E;
1302
                                                dir[1].Name[1] = 0x2E;
1302
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1303
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1303
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1304
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1304
                                                dir[1].StartCluster = dircluster;
1305
                                                dir[1].StartCluster = dircluster;
1305
                                                dir[1].Size = 0;
1306
                                                dir[1].Size = 0;
1306
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1307
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1307
                                                {
1308
                                                {
1308
                                                        Fat16_Deinit();
1309
                                                        Fat16_Deinit();
1309
                                                        return(retvalue);
1310
                                                        return(retvalue);
1310
                                                }
1311
                                                }
1311
                                        }
1312
                                        }
1312
                                        retvalue = 1;
1313
                                        retvalue = 1;
1313
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1314
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1314
                                }
1315
                                }
1315
                        }
1316
                        }
1316
                        dir_sector++; // search next sector
1317
                        dir_sector++; // search next sector
1317
                // stop if we reached the end of the cluster or the end of the root dir
1318
                // stop if we reached the end of the cluster or the end of the root dir
1318
                }while((dir_sector < max_dir_sector) && (!retvalue));
1319
                }while((dir_sector < max_dir_sector) && (!retvalue));
1319
 
1320
 
1320
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1321
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1321
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1322
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1322
                {
1323
                {
1323
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1324
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1324
                }
1325
                }
1325
        }while((end_of_directory_not_reached) && (!retvalue));
1326
        }while((end_of_directory_not_reached) && (!retvalue));
1326
        // Perhaps we are at the end of the last cluster of a directory file and have no free direntry found.
1327
        // Perhaps we are at the end of the last cluster of a directory file and have no free direntry found.
1327
        // Then we would need to add a cluster to that file and create the new direntry there.
1328
        // Then we would need to add a cluster to that file and create the new direntry there.
1328
        // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1329
        // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1329
        // within a subdirectory of root.
1330
        // within a subdirectory of root.
1330
 
1331
 
1331
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1332
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1332
}
1333
}
1333
 
1334
 
1334
/********************************************************************************************************************************************/
1335
/********************************************************************************************************************************************/
1335
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
1336
/*      Function:               FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file);                                                                                    */
1336
/*                                                                                                                                                                                                                                                                                      */
1337
/*                                                                                                                                                                                                                                                                                      */
1337
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1338
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1338
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
1339
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
1339
/*                                      updated.                                                                                                                                                                                                                                */
1340
/*                                      updated.                                                                                                                                                                                                                                */
1340
/*                                                                                                                                                                                                                                                                                      */
1341
/*                                                                                                                                                                                                                                                                                      */
1341
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1342
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1342
/********************************************************************************************************************************************/
1343
/********************************************************************************************************************************************/
1343
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
1344
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
1344
{
1345
{
1345
        s8* path = 0;
1346
        s8* path = 0;
1346
        s8* subpath = 0;
1347
        s8* subpath = 0;
1347
        u8 af, am, file_exist = 0;
1348
        u8 af, am, file_exist = 0;
1348
        s8 dirname[12]; // 8+3 + temination character
1349
        s8 dirname[12]; // 8+3 + temination character
1349
 
1350
 
1350
        // if incomming pointers are useless return immediatly
1351
        // if incomming pointers are useless return immediatly
1351
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1352
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1352
 
1353
 
1353
        // trace along the filepath
1354
        // trace along the filepath
1354
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1355
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1355
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1356
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1356
        file->DirectoryIndex = 0;
1357
        file->DirectoryIndex = 0;
1357
        // as long as the file was not found and the remaining path is not empty
1358
        // as long as the file was not found and the remaining path is not empty
1358
        while((*path != 0) && !file_exist)
1359
        while((*path != 0) && !file_exist)
1359
        {       // separate dirname and subpath from filepath string
1360
        {       // separate dirname and subpath from filepath string
1360
                subpath = SeperateDirName(path, dirname);
1361
                subpath = SeperateDirName(path, dirname);
1361
                if(subpath != NULL)
1362
                if(subpath != NULL)
1362
                {
1363
                {
1363
                        if(*subpath == 0)
1364
                        if(*subpath == 0)
1364
                        {       // empty subpath indicates last element of dir chain
1365
                        {       // empty subpath indicates last element of dir chain
1365
                                af = attribfilter;
1366
                                af = attribfilter;
1366
                                am = attribmask;
1367
                                am = attribmask;
1367
                        }
1368
                        }
1368
                        else  // it must be a subdirectory and no volume label
1369
                        else  // it must be a subdirectory and no volume label
1369
                        {
1370
                        {
1370
                                af = ATTR_SUBDIRECTORY;
1371
                                af = ATTR_SUBDIRECTORY;
1371
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1372
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1372
                        }
1373
                        }
1373
                        if(!DirectoryEntryExist(dirname, af, am, file))
1374
                        if(!DirectoryEntryExist(dirname, af, am, file))
1374
                        {
1375
                        {
1375
                                return (file_exist); // subdirectory does not exist
1376
                                return (file_exist); // subdirectory does not exist
1376
                        }
1377
                        }
1377
                        else
1378
                        else
1378
                        {
1379
                        {
1379
                                if (*subpath == 0)
1380
                                if (*subpath == 0)
1380
                                {
1381
                                {
1381
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1382
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1382
                                }
1383
                                }
1383
                        }
1384
                        }
1384
                }
1385
                }
1385
                else // error seperating the subpath
1386
                else // error seperating the subpath
1386
                {
1387
                {
1387
                        return file_exist; // bad subdir format
1388
                        return file_exist; // bad subdir format
1388
                }
1389
                }
1389
                path = subpath;
1390
                path = subpath;
1390
                subpath = 0;
1391
                subpath = 0;
1391
        }
1392
        }
1392
        return (file_exist);
1393
        return (file_exist);
1393
}
1394
}
1394
 
1395
 
1395
 
1396
 
1396
/********************************************************************************************************************************************/
1397
/********************************************************************************************************************************************/
1397
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1398
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1398
/*                                                                                                                                                                                                                                                                                      */
1399
/*                                                                                                                                                                                                                                                                                      */
1399
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1400
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1400
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1401
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1401
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1402
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1402
/*                                                                                                                                                                                                                                                                                      */
1403
/*                                                                                                                                                                                                                                                                                      */
1403
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1404
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1404
/********************************************************************************************************************************************/
1405
/********************************************************************************************************************************************/
1405
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1406
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1406
{
1407
{
1407
        s8 *path = 0;
1408
        s8 *path = 0;
1408
        s8 *subpath = 0;
1409
        s8 *subpath = 0;
1409
        u8 af, am, file_created = 0;
1410
        u8 af, am, file_created = 0;
1410
        s8 dirname[12];
1411
        s8 dirname[12];
1411
 
1412
 
1412
        // if incomming pointers are useless return immediatly
1413
        // if incomming pointers are useless return immediatly
1413
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1414
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1414
 
1415
 
1415
        // trace along the filepath
1416
        // trace along the filepath
1416
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
1417
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
1417
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1418
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1418
        file->DirectoryIndex = 0;
1419
        file->DirectoryIndex = 0;
1419
        // as long as the file was not created and the remaining file path is not empty
1420
        // as long as the file was not created and the remaining file path is not empty
1420
        while((*path != 0) && !file_created)
1421
        while((*path != 0) && !file_created)
1421
        {   // separate dirname and subpath from filepath string
1422
        {   // separate dirname and subpath from filepath string
1422
                subpath = SeperateDirName(path, dirname);
1423
                subpath = SeperateDirName(path, dirname);
1423
                if(subpath != NULL)
1424
                if(subpath != NULL)
1424
                {
1425
                {
1425
                        if(*subpath == 0)
1426
                        if(*subpath == 0)
1426
                        {       // empty subpath indicates last element of dir chain
1427
                        {       // empty subpath indicates last element of dir chain
1427
                                af = ATTR_NONE;
1428
                                af = ATTR_NONE;
1428
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1429
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1429
                        }
1430
                        }
1430
                        else  // it must be a subdirectory and no volume label
1431
                        else  // it must be a subdirectory and no volume label
1431
                        {
1432
                        {
1432
                                af = ATTR_SUBDIRECTORY;
1433
                                af = ATTR_SUBDIRECTORY;
1433
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1434
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1434
                        }
1435
                        }
1435
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1436
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1436
                        {  // try to create subdir or file
1437
                        {  // try to create subdir or file
1437
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1438
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1438
                                if(!CreateDirectoryEntry(dirname, af, file))
1439
                                if(!CreateDirectoryEntry(dirname, af, file))
1439
                                {       // could not be created
1440
                                {       // could not be created
1440
                                        return(file_created);
1441
                                        return(file_created);
1441
                                }
1442
                                }
1442
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1443
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1443
                        }
1444
                        }
1444
                }
1445
                }
1445
                else // error seperating the subpath
1446
                else // error seperating the subpath
1446
                {
1447
                {
1447
                        return file_created; // bad subdir format
1448
                        return file_created; // bad subdir format
1448
                }
1449
                }
1449
                path = subpath;
1450
                path = subpath;
1450
                subpath = 0;
1451
                subpath = 0;
1451
        }
1452
        }
1452
        return (file_created);
1453
        return (file_created);
1453
}
1454
}
1454
 
1455
 
1455
 
1456
 
1456
/********************************************************************************************************************************************/
1457
/********************************************************************************************************************************************/
1457
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1458
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1458
/*                                                                                                                                                                                                                                                                                      */
1459
/*                                                                                                                                                                                                                                                                                      */
1459
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1460
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1460
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1461
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1461
/*                                                                                                                                                                                                                                                                                      */
1462
/*                                                                                                                                                                                                                                                                                      */
1462
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1463
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1463
/********************************************************************************************************************************************/
1464
/********************************************************************************************************************************************/
1464
File_t * fopen_(s8 * const filename, const s8 mode)
1465
File_t * fopen_(s8 * const filename, const s8 mode)
1465
{
1466
{
1466
        File_t *file    = 0;
1467
        File_t *file    = 0;
1467
 
1468
 
1468
        if((!Partition.IsValid) || (filename == 0)) return(file);
1469
        if((!Partition.IsValid) || (filename == 0)) return(file);
1469
 
1470
 
1470
        // Look for an unused filepointer in the file pointer list?
1471
        // Look for an unused filepointer in the file pointer list?
1471
        file = LockFilePointer();
1472
        file = LockFilePointer();
1472
        // if no unused file pointer was found return 0
1473
        // if no unused file pointer was found return 0
1473
        if(file == NULL) return(file);
1474
        if(file == NULL) return(file);
1474
 
1475
 
1475
        // now we have found a free filepointer and claimed it
1476
        // now we have found a free filepointer and claimed it
1476
        // so let initiate its property values
1477
        // so let initiate its property values
1477
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;             // Sectorpointer to the first sector of the first datacluster of the file.
1478
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;             // Sectorpointer to the first sector of the first datacluster of the file.
1478
        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;             // Pointer to the cluster which is edited at the moment.
1479
        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;             // Pointer to the cluster which is edited at the moment.
1479
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1480
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1480
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1481
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1481
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1482
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1482
        file->Size                                              = 0;            // the size of the opened file in bytes.
1483
        file->Size                                              = 0;            // the size of the opened file in bytes.
1483
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1484
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1484
        file->SectorInCache                             = SECTOR_UNDEFINED;             // the last sector read, wich is still in the sectorbuffer.
1485
        file->SectorInCache                             = SECTOR_UNDEFINED;             // the last sector read, wich is still in the sectorbuffer.
1485
        file->DirectorySector                   = SECTOR_UNDEFINED;             // the sectorposition where the directoryentry has been made.
1486
        file->DirectorySector                   = SECTOR_UNDEFINED;             // the sectorposition where the directoryentry has been made.
1486
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1487
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1487
        file->Attribute                                 = 0;            // the attribute of the file opened.
1488
        file->Attribute                                 = 0;            // the attribute of the file opened.
1488
 
1489
 
1489
        // check if a real file (no directory) to the given filename exist
1490
        // check if a real file (no directory) to the given filename exist
1490
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1491
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1491
        {  // file exist
1492
        {  // file exist
1492
                switch(mode)  // check mode
1493
                switch(mode)  // check mode
1493
                {
1494
                {
1494
                        case 'a':       // if mode is: append to file
1495
                        case 'a':       // if mode is: append to file
1495
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1496
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1496
                                {       // file is marked as readonly --> do not open this file
1497
                                {       // file is marked as readonly --> do not open this file
1497
                                        fclose_(file);
1498
                                        fclose_(file);
1498
                                        file = NULL;
1499
                                        file = NULL;
1499
                                }
1500
                                }
1500
                                else
1501
                                else
1501
                                {       // file is not marked as read only --> goto end of file
1502
                                {       // file is not marked as read only --> goto end of file
1502
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1503
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1503
                                }
1504
                                }
1504
                                break;
1505
                                break;
1505
                        case 'w':       // if mode is: write to file
1506
                        case 'w':       // if mode is: write to file
1506
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1507
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1507
                                {       // file is marked as readonly --> do not open this file
1508
                                {       // file is marked as readonly --> do not open this file
1508
                                        fclose_(file);
1509
                                        fclose_(file);
1509
                                        file = NULL;
1510
                                        file = NULL;
1510
                                }
1511
                                }
1511
                                else
1512
                                else
1512
                                {       // file is not marked as read only
1513
                                {       // file is not marked as read only
1513
                                        DirEntry_t * dir;
1514
                                        DirEntry_t * dir;
1514
                                        // free all clusters of that file
1515
                                        // free all clusters of that file
1515
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1516
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1516
                                        // update directory entry of that file
1517
                                        // update directory entry of that file
1517
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1518
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1518
                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1519
                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1519
                                        {
1520
                                        {
1520
                                                Fat16_Deinit();
1521
                                                Fat16_Deinit();
1521
                                                return(NULL);
1522
                                                return(NULL);
1522
                                        }
1523
                                        }
1523
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1524
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1524
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1525
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1525
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1526
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1526
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1527
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1527
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster 
1528
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster 
1528
                                        dir[file->DirectoryIndex].Size          = 0;
1529
                                        dir[file->DirectoryIndex].Size          = 0;
1529
                                        // write sector containing the direntry
1530
                                        // write sector containing the direntry
1530
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1531
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1531
                                        {
1532
                                        {
1532
                                                Fat16_Deinit();
1533
                                                Fat16_Deinit();
1533
                                                return(NULL);
1534
                                                return(NULL);
1534
                                        }
1535
                                        }
1535
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1536
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1536
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1537
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1537
                                        file->SectorOfCurrCluster = 0;
1538
                                        file->SectorOfCurrCluster = 0;
1538
                                        file->ByteOfCurrSector = 0;
1539
                                        file->ByteOfCurrSector = 0;
1539
                                        file->Size = 0;
1540
                                        file->Size = 0;
1540
                                        file->Position = 0;
1541
                                        file->Position = 0;
1541
                                        fseek_(file, 0, SEEK_SET);
1542
                                        fseek_(file, 0, SEEK_SET);
1542
                                }
1543
                                }
1543
                                break;
1544
                                break;
1544
                        case 'r':       // if mode is: read from file
1545
                        case 'r':       // if mode is: read from file
1545
                                // goto end of file
1546
                                // goto end of file
1546
                                fseek_(file, 0, SEEK_SET);
1547
                                fseek_(file, 0, SEEK_SET);
1547
                                break;
1548
                                break;
1548
                        default: // other modes are not supported
1549
                        default: // other modes are not supported
1549
                                fclose_(file);
1550
                                fclose_(file);
1550
                                file = NULL;
1551
                                file = NULL;
1551
                        break;
1552
                        break;
1552
                }
1553
                }
1553
                return(file);
1554
                return(file);
1554
        }
1555
        }
1555
        else // file does not exist
1556
        else // file does not exist
1556
        {
1557
        {
1557
                switch(mode)  // check mode
1558
                switch(mode)  // check mode
1558
                {
1559
                {
1559
                        case 'a':
1560
                        case 'a':
1560
                        case 'w': // if mode is write or append
1561
                        case 'w': // if mode is write or append
1561
                                // try to create the file
1562
                                // try to create the file
1562
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1563
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1563
                                { // if it could not be created
1564
                                { // if it could not be created
1564
                                        fclose_(file);
1565
                                        fclose_(file);
1565
                                        file = NULL;
1566
                                        file = NULL;
1566
                                }
1567
                                }
1567
                                break;
1568
                                break;
1568
                        case 'r': // else opened for 'r'
1569
                        case 'r': // else opened for 'r'
1569
                        default:  // if unsupported mode
1570
                        default:  // if unsupported mode
1570
                                fclose_(file);
1571
                                fclose_(file);
1571
                                file = NULL;
1572
                                file = NULL;
1572
                                break;
1573
                                break;
1573
                }
1574
                }
1574
                return(file);
1575
                return(file);
1575
        }
1576
        }
1576
        // we should never come to this point
1577
        // we should never come to this point
1577
        fclose_(file);
1578
        fclose_(file);
1578
        file = NULL;
1579
        file = NULL;
1579
        return(file);
1580
        return(file);
1580
}
1581
}
1581
 
1582
 
1582
/****************************************************************************************************************************************************/
1583
/****************************************************************************************************************************************************/
1583
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1584
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1584
/*                                                                                                                                                                                                                                                                                                      */
1585
/*                                                                                                                                                                                                                                                                                                      */
1585
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1586
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1586
/*                                                                                                                                                                                                                                                                                                      */
1587
/*                                                                                                                                                                                                                                                                                                      */
1587
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1588
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1588
/****************************************************************************************************************************************************/
1589
/****************************************************************************************************************************************************/
1589
s16     fflush_(File_t *file)
1590
s16     fflush_(File_t *file)
1590
{
1591
{
1591
        DirEntry_t *dir;
1592
        DirEntry_t *dir;
1592
 
1593
 
1593
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1594
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1594
 
1595
 
1595
        switch(file->Mode)
1596
        switch(file->Mode)
1596
        {
1597
        {
1597
                case 'a':
1598
                case 'a':
1598
                case 'w':
1599
                case 'w':
1599
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1600
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1600
                        {
1601
                        {
1601
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1602
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1602
                                {
1603
                                {
1603
                                        Fat16_Deinit();
1604
                                        Fat16_Deinit();
1604
                                        return(EOF);
1605
                                        return(EOF);
1605
                                }
1606
                                }
1606
                        }
1607
                        }
1607
                        file->SectorInCache     = file->DirectorySector;
1608
                        file->SectorInCache     = file->DirectorySector;
1608
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1609
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1609
                        {
1610
                        {
1610
                                Fat16_Deinit();
1611
                                Fat16_Deinit();
1611
                                return(EOF);
1612
                                return(EOF);
1612
                        }
1613
                        }
1613
 
1614
 
1614
                        dir = (DirEntry_t *)file->Cache;
1615
                        dir = (DirEntry_t *)file->Cache;
1615
                        // update dile size and modification time & date
1616
                        // update dile size and modification time & date
1616
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1617
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1617
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1618
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1618
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1619
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1619
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1620
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1620
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1621
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1621
                        {
1622
                        {
1622
                                Fat16_Deinit();
1623
                                Fat16_Deinit();
1623
                                return(EOF);
1624
                                return(EOF);
1624
                        }
1625
                        }
1625
                        break;
1626
                        break;
1626
                case 'r':
1627
                case 'r':
1627
                default:
1628
                default:
1628
                        // do nothing!
1629
                        // do nothing!
1629
                        return(EOF);
1630
                        return(EOF);
1630
                        break;
1631
                        break;
1631
 
1632
 
1632
        }
1633
        }
1633
        return(0);
1634
        return(0);
1634
}
1635
}
1635
 
1636
 
1636
/****************************************************************************************************************************************/
1637
/****************************************************************************************************************************************/
1637
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1638
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1638
/*                                                                                                                                                                                                                                                                              */
1639
/*                                                                                                                                                                                                                                                                              */
1639
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1640
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1640
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1641
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1641
/*                                                                                                                                                                                                                                                                              */
1642
/*                                                                                                                                                                                                                                                                              */
1642
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1643
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1643
/****************************************************************************************************************************************/
1644
/****************************************************************************************************************************************/
1644
s16 fclose_(File_t *file)
1645
s16 fclose_(File_t *file)
1645
{
1646
{
1646
        s16 returnvalue = EOF;
1647
        s16 returnvalue = EOF;
1647
 
1648
 
1648
        if(file == NULL) return(returnvalue);
1649
        if(file == NULL) return(returnvalue);
1649
        returnvalue = fflush_(file);
1650
        returnvalue = fflush_(file);
1650
        UnlockFilePointer(file);
1651
        UnlockFilePointer(file);
1651
        return(returnvalue);
1652
        return(returnvalue);
1652
}
1653
}
1653
 
1654
 
1654
/********************************************************************************************************************************************/
1655
/********************************************************************************************************************************************/
1655
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1656
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1656
/*                                                                                                                                                                                                                                                                                      */
1657
/*                                                                                                                                                                                                                                                                                      */
1657
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1658
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1658
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1659
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1659
/*                                                                                                                                                                                                                                                                                      */
1660
/*                                                                                                                                                                                                                                                                                      */
1660
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1661
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1661
/********************************************************************************************************************************************/
1662
/********************************************************************************************************************************************/
1662
s16 fgetc_(File_t *file)
1663
s16 fgetc_(File_t *file)
1663
{
1664
{
1664
        s16 c = EOF;
1665
        s16 c = EOF;
1665
        u32 curr_sector;
1666
        u32 curr_sector;
1666
 
1667
 
1667
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1668
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1668
        // if the end of the file is not reached, get the next character.
1669
        // if the end of the file is not reached, get the next character.
1669
        if((0 < file->Size) && ((file->Position+1) < file->Size) )
1670
        if((0 < file->Size) && ((file->Position+1) < file->Size) )
1670
        {
1671
        {
1671
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1672
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1672
                curr_sector += file->SectorOfCurrCluster;
1673
                curr_sector += file->SectorOfCurrCluster;
1673
 
1674
 
1674
                if(file->SectorInCache != curr_sector)
1675
                if(file->SectorInCache != curr_sector)
1675
                {
1676
                {
1676
                        file->SectorInCache = curr_sector;
1677
                        file->SectorInCache = curr_sector;
1677
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1678
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1678
                        {
1679
                        {
1679
                                Fat16_Deinit();
1680
                                Fat16_Deinit();
1680
                                return(c);
1681
                                return(c);
1681
                        }
1682
                        }
1682
                }
1683
                }
1683
                c = (s16) file->Cache[file->ByteOfCurrSector];
1684
                c = (s16) file->Cache[file->ByteOfCurrSector];
1684
                file->Position++;                                                                       // increment file position
1685
                file->Position++;                                                                       // increment file position
1685
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1686
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1686
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1687
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1687
                {
1688
                {
1688
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1689
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1689
                        file->SectorOfCurrCluster++;                                    //      next sector
1690
                        file->SectorOfCurrCluster++;                                    //      next sector
1690
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1691
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1691
                        {
1692
                        {
1692
 
1693
 
1693
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1694
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1694
                                {
1695
                                {
1695
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1696
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1696
                                }
1697
                                }
1697
                                else // the last cluster was allready reached
1698
                                else // the last cluster was allready reached
1698
                                {
1699
                                {
1699
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1700
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1700
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1701
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1701
                                }
1702
                                }
1702
                        }
1703
                        }
1703
                }
1704
                }
1704
        }
1705
        }
1705
        return(c);
1706
        return(c);
1706
}
1707
}
1707
 
1708
 
1708
/********************************************************************************************************************************************/
1709
/********************************************************************************************************************************************/
1709
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1710
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1710
/*                                                                                                                                                                                                                                                                                      */
1711
/*                                                                                                                                                                                                                                                                                      */
1711
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1712
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1712
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1713
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1713
/*                                                                                                                                                                                                                                                                                      */
1714
/*                                                                                                                                                                                                                                                                                      */
1714
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1715
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1715
/********************************************************************************************************************************************/
1716
/********************************************************************************************************************************************/
1716
s16 fputc_(const s8 c, File_t *file)
1717
s16 fputc_(const s8 c, File_t *file)
1717
{
1718
{
1718
        u32 curr_sector  = 0;
1719
        u32 curr_sector  = 0;
1719
 
1720
 
1720
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1721
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1721
        switch(file->Mode)
1722
        switch(file->Mode)
1722
        {
1723
        {
1723
                case 'w':
1724
                case 'w':
1724
                case 'a':
1725
                case 'a':
1725
                        // If file position equals to file size, then the end of file has been reached.
1726
                        // If file position equals to file size, then the end of file has been reached.
1726
                        // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1727
                        // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1727
                        // and a new cluster should be appended.
1728
                        // and a new cluster should be appended.
1728
                        // If the first sector of first cluster is unvalid, then the file claims no data clusters 
1729
                        // If the first sector of first cluster is unvalid, then the file claims no data clusters 
1729
                        // and size should be zero, therefore append a new Cluster too.
1730
                        // and size should be zero, therefore append a new Cluster too.
1730
                        if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED))
1731
                        if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED))
1731
                        {
1732
                        {
1732
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1733
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1733
                        }
1734
                        }
1734
               
1735
               
1735
                        curr_sector  = file->FirstSectorOfCurrCluster;
1736
                        curr_sector  = file->FirstSectorOfCurrCluster;
1736
                        curr_sector += file->SectorOfCurrCluster;
1737
                        curr_sector += file->SectorOfCurrCluster;
1737
                        if(file->SectorInCache != curr_sector)
1738
                        if(file->SectorInCache != curr_sector)
1738
                        {
1739
                        {
1739
                                file->SectorInCache = curr_sector;
1740
                                file->SectorInCache = curr_sector;
1740
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1741
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1741
                                {
1742
                                {
1742
                                        Fat16_Deinit();
1743
                                        Fat16_Deinit();
1743
                                        return(EOF);
1744
                                        return(EOF);
1744
                                }
1745
                                }
1745
                        }
1746
                        }
1746
               
1747
               
1747
                        file->Cache[file->ByteOfCurrSector] = (u8)c;            // write databyte into the buffer. The byte will be written to the device at once
1748
                        file->Cache[file->ByteOfCurrSector] = (u8)c;            // write databyte into the buffer. The byte will be written to the device at once
1748
                        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.
1749
                        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.
1749
                        file->Position++;                                                                       // the actual positon within the file.
1750
                        file->Position++;                                                                       // the actual positon within the file.
1750
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1751
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1751
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1752
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1752
                        {       // save the sector to the sd-card
1753
                        {       // save the sector to the sd-card
1753
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1754
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1754
                                {
1755
                                {
1755
                                        Fat16_Deinit();
1756
                                        Fat16_Deinit();
1756
                                        return(EOF);
1757
                                        return(EOF);
1757
                                }
1758
                                }
1758
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1759
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1759
                                file->SectorOfCurrCluster++;                                    //      next sector
1760
                                file->SectorOfCurrCluster++;                                    //      next sector
1760
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1761
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1761
                                {
1762
                                {
1762
                                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1763
                                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1763
                                        { // if current cluster was the last cluster of the file
1764
                                        { // if current cluster was the last cluster of the file
1764
                                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1765
                                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1765
                                                {
1766
                                                {
1766
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1767
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1767
                                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1768
                                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1768
                                                        return(EOF);
1769
                                                        return(EOF);
1769
                                                }
1770
                                                }
1770
                                        }
1771
                                        }
1771
                                        else // next cluster
1772
                                        else // next cluster
1772
                                        {
1773
                                        {
1773
                                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1774
                                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1774
                                        }
1775
                                        }
1775
                                }
1776
                                }
1776
                        }
1777
                        }
1777
                        break;
1778
                        break;
1778
                case 'r':
1779
                case 'r':
1779
                default:
1780
                default:
1780
                        return(EOF);
1781
                        return(EOF);
1781
                        break;
1782
                        break;
1782
        } // EOF switch(file->Mode)
1783
        } // EOF switch(file->Mode)
1783
        return(0);
1784
        return(0);
1784
}
1785
}
1785
 
1786
 
1786
 
1787
 
1787
/****************************************************************************************************************************************/
1788
/****************************************************************************************************************************************/
1788
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1789
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1789
/*                                                                                                                                                                                                                                                                              */
1790
/*                                                                                                                                                                                                                                                                              */
1790
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1791
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1791
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1792
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1792
/*                                                                                                                                                                                                                                                                              */
1793
/*                                                                                                                                                                                                                                                                              */
1793
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1794
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1794
/****************************************************************************************************************************************/
1795
/****************************************************************************************************************************************/
1795
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1796
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1796
{
1797
{
1797
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1798
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1798
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1799
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1799
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1800
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1800
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1801
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1801
        s16 c;
1802
        s16 c;
1802
 
1803
 
1803
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1804
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1804
 
1805
 
1805
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1806
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1806
 
1807
 
1807
        while((object_cnt < count) && success)
1808
        while((object_cnt < count) && success)
1808
        {
1809
        {
1809
                object_size = size;
1810
                object_size = size;
1810
                while((size > 0) && success)
1811
                while((size > 0) && success)
1811
                {
1812
                {
1812
                        c = fgetc_(file);
1813
                        c = fgetc_(file);
1813
                        if(c != EOF)
1814
                        if(c != EOF)
1814
                        {
1815
                        {
1815
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1816
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1816
                                pbuff++;
1817
                                pbuff++;
1817
                                size--;
1818
                                size--;
1818
                        }
1819
                        }
1819
                        else // error or end of file reached
1820
                        else // error or end of file reached
1820
                        {
1821
                        {
1821
                                success = 0;
1822
                                success = 0;
1822
                        }
1823
                        }
1823
                }
1824
                }
1824
                if(success) object_cnt++;
1825
                if(success) object_cnt++;
1825
        }
1826
        }
1826
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1827
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1827
}
1828
}
1828
 
1829
 
1829
 
1830
 
1830
/****************************************************************************************************************************************/
1831
/****************************************************************************************************************************************/
1831
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1832
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1832
/*                                                                                                                                                                                                                                                                              */
1833
/*                                                                                                                                                                                                                                                                              */
1833
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1834
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1834
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1835
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1835
/*                                                                                                                                                                                                                                                                              */
1836
/*                                                                                                                                                                                                                                                                              */
1836
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1837
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1837
/****************************************************************************************************************************************/
1838
/****************************************************************************************************************************************/
1838
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
1839
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
1839
{
1840
{
1840
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1841
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1841
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
1842
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
1842
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1843
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1843
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1844
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1844
        s16 c;
1845
        s16 c;
1845
 
1846
 
1846
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1847
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1847
        if(file->Mode == 'r') return (0); // opened read only
1848
        if(file->Mode == 'r') return (0); // opened read only
1848
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1849
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1849
 
1850
 
1850
        while((object_cnt < count) && success)
1851
        while((object_cnt < count) && success)
1851
        {
1852
        {
1852
                object_size = size;
1853
                object_size = size;
1853
                while((size > 0) && success)
1854
                while((size > 0) && success)
1854
                {
1855
                {
1855
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1856
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1856
                        if(c != EOF)
1857
                        if(c != EOF)
1857
                        {
1858
                        {
1858
                                pbuff++;
1859
                                pbuff++;
1859
                                size--;
1860
                                size--;
1860
                        }
1861
                        }
1861
                        else
1862
                        else
1862
                        {
1863
                        {
1863
                                success = 0;
1864
                                success = 0;
1864
                        }
1865
                        }
1865
                }
1866
                }
1866
                if(success) object_cnt++;
1867
                if(success) object_cnt++;
1867
        }
1868
        }
1868
 
1869
 
1869
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1870
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1870
}
1871
}
1871
 
1872
 
1872
 
1873
 
1873
/****************************************************************************************************************************************/
1874
/****************************************************************************************************************************************/
1874
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1875
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1875
/*                                                                                                                                                                                                                                                                              */
1876
/*                                                                                                                                                                                                                                                                              */
1876
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1877
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1877
/*                                                                                                                                                                                                                                                                              */
1878
/*                                                                                                                                                                                                                                                                              */
1878
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1879
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1879
/****************************************************************************************************************************************/
1880
/****************************************************************************************************************************************/
1880
s16 fputs_(s8 * const string, File_t * const file)
1881
s16 fputs_(s8 * const string, File_t * const file)
1881
{
1882
{
1882
        u8 i=0;
1883
        u8 i=0;
1883
        s16 c = 0;
1884
        s16 c = 0;
1884
 
1885
 
1885
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
1886
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
1886
        if(file->Mode == 'r') return(EOF);
1887
        if(file->Mode == 'r') return(EOF);
1887
        while((string[i] != 0)&& (c != EOF))
1888
        while((string[i] != 0)&& (c != EOF))
1888
        {
1889
        {
1889
                c = fputc_(string[i], file);
1890
                c = fputc_(string[i], file);
1890
                i++;
1891
                i++;
1891
        }
1892
        }
1892
        return(c);
1893
        return(c);
1893
}
1894
}
1894
 
1895
 
1895
/****************************************************************************************************************************************/
1896
/****************************************************************************************************************************************/
1896
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
1897
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
1897
/*                                                                                                                                                                                                                                                                              */
1898
/*                                                                                                                                                                                                                                                                              */
1898
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1899
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1899
/*                                                                                                                                                                                                                                                                              */
1900
/*                                                                                                                                                                                                                                                                              */
1900
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1901
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1901
/****************************************************************************************************************************************/
1902
/****************************************************************************************************************************************/
1902
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
1903
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
1903
{
1904
{
1904
        s8 *pbuff;
1905
        s8 *pbuff;
1905
        s16 c = 0, bytecount;
1906
        s16 c = 0, bytecount;
1906
 
1907
 
1907
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
1908
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
1908
        bytecount = length;
1909
        bytecount = length;
1909
        pbuff = string;                                                         // set write pointer to start of string
1910
        pbuff = string;                                                         // set write pointer to start of string
1910
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
1911
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
1911
        {
1912
        {
1912
                c = fgetc_(file);                                               // read a character from the opened file.
1913
                c = fgetc_(file);                                               // read a character from the opened file.
1913
                switch(c)
1914
                switch(c)
1914
                {
1915
                {
1915
                        case 0x0A:                                                      // new line
1916
                        case 0x0A:                                                      // new line
1916
                                *pbuff = 0;                                             // set string terminator
1917
                                *pbuff = 0;                                             // set string terminator
1917
                                return(string);                                 // return normal
1918
                                return(string);                                 // return normal
1918
 
1919
 
1919
                        case EOF:
1920
                        case EOF:
1920
                                *pbuff = 0;                                             // set string terminator
1921
                                *pbuff = 0;                                             // set string terminator
1921
                                return(0);
1922
                                return(0);
1922
 
1923
 
1923
                        default:
1924
                        default:
1924
                                *pbuff++ = (s8)c;                               // copy byte to string
1925
                                *pbuff++ = (s8)c;                               // copy byte to string
1925
                                bytecount--;
1926
                                bytecount--;
1926
                                break;
1927
                                break;
1927
                }
1928
                }
1928
        }
1929
        }
1929
        *pbuff = 0;     // set string terminator
1930
        *pbuff = 0;     // set string terminator
1930
        return(string);
1931
        return(string);
1931
}
1932
}
1932
 
1933
 
1933
/****************************************************************************************************************************************/
1934
/****************************************************************************************************************************************/
1934
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
1935
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
1935
/*                                                                                                                                                                                                                                                                              */
1936
/*                                                                                                                                                                                                                                                                              */
1936
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1937
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1937
/*                                                                                                                                                                                                                                                                              */
1938
/*                                                                                                                                                                                                                                                                              */
1938
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1939
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1939
/****************************************************************************************************************************************/
1940
/****************************************************************************************************************************************/
1940
u8 fexist_(s8 * const filename)
1941
u8 fexist_(s8 * const filename)
1941
{
1942
{
1942
        u8 exist = 0;
1943
        u8 exist = 0;
1943
        File_t *file = 0;
1944
        File_t *file = 0;
1944
        file = LockFilePointer();
1945
        file = LockFilePointer();
1945
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1946
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1946
        UnlockFilePointer(file);
1947
        UnlockFilePointer(file);
1947
        return(exist);
1948
        return(exist);
1948
}
1949
}
1949
 
1950
 
1950
/****************************************************************************************************************************************/
1951
/****************************************************************************************************************************************/
1951
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1952
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1952
/*                                                                                                                                                                                                                                                                              */
1953
/*                                                                                                                                                                                                                                                                              */
1953
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1954
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1954
/*                                                                                                                                                                                                                                                                              */
1955
/*                                                                                                                                                                                                                                                                              */
1955
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1956
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1956
/****************************************************************************************************************************************/
1957
/****************************************************************************************************************************************/
1957
u8 feof_(File_t *file)
1958
u8 feof_(File_t *file)
1958
{
1959
{
1959
        if(((file->Position)+1) < (file->Size))
1960
        if(((file->Position)+1) < (file->Size))
1960
        {
1961
        {
1961
                return(0);
1962
                return(0);
1962
        }
1963
        }
1963
        else
1964
        else
1964
        {
1965
        {
1965
                return(1);
1966
                return(1);
1966
        }
1967
        }
1967
}
1968
}
1968
 
1969
 
1969
/****************************************************************************************************************************************************/
1970
/****************************************************************************************************************************************************/
1970
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
1971
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
1971
/*                                                                                                                                                                                                                                                                                                      */
1972
/*                                                                                                                                                                                                                                                                                                      */
1972
/* Description: This function returns the volume label                                                                                                                                                                                          */
1973
/* Description: This function returns the volume label                                                                                                                                                                                          */
1973
/*                                                                                                                                                                                                                                                                                                      */
1974
/*                                                                                                                                                                                                                                                                                                      */
1974
/* Returnvalue: This function returns the pointer to the volume label or NULL if not found.                                                                                                                     */
1975
/* Returnvalue: This function returns the pointer to the volume label or NULL if not found.                                                                                                                     */
1975
/****************************************************************************************************************************************************/
1976
/****************************************************************************************************************************************************/
1976
s8* FAT16_GetVolumeLabel(void)
1977
s8* FAT16_GetVolumeLabel(void)
1977
{
1978
{
1978
        s8              *pVolumeLabel = NULL;
1979
        s8              *pVolumeLabel = NULL;
1979
        u32             dir_sector, max_dir_sector, curr_sector;
1980
        u32             dir_sector, max_dir_sector, curr_sector;
1980
        u16     dir_entry = 0;
1981
        u16     dir_entry = 0;
1981
        u8              i = 0;
1982
        u8              i = 0;
1982
 
1983
 
1983
        DirEntry_t * dir;
1984
        DirEntry_t * dir;
1984
        File_t *file = NULL;
1985
        File_t *file = NULL;
1985
       
1986
       
1986
        // if Partition is not valud return NULL
1987
        // if Partition is not valud return NULL
1987
        if(!Partition.IsValid) return(pVolumeLabel);
1988
        if(!Partition.IsValid) return(pVolumeLabel);
1988
        // if Volume label was read before return it
1989
        // if Volume label was read before return it
1989
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
1990
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
1990
        // try to catch a file pointer
1991
        // try to catch a file pointer
1991
        file = LockFilePointer();
1992
        file = LockFilePointer();
1992
        if(file == NULL) return(pVolumeLabel);
1993
        if(file == NULL) return(pVolumeLabel);
1993
        // search dir entries direct within the root directory area
1994
        // search dir entries direct within the root directory area
1994
        file->DirectorySector = 0;
1995
        file->DirectorySector = 0;
1995
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1996
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1996
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1997
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1997
       
1998
       
1998
        // update current file data area position to start of first cluster
1999
        // update current file data area position to start of first cluster
1999
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2000
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2000
        file->SectorOfCurrCluster               = 0;
2001
        file->SectorOfCurrCluster               = 0;
2001
        file->ByteOfCurrSector                  = 0;
2002
        file->ByteOfCurrSector                  = 0;
2002
 
2003
 
2003
        dir_sector = 0; // reset sector counter within a new cluster
2004
        dir_sector = 0; // reset sector counter within a new cluster
2004
        do // loop over all sectors of the root directory
2005
        do // loop over all sectors of the root directory
2005
        {
2006
        {
2006
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2007
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2007
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2008
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2008
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
2009
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
2009
                {
2010
                {
2010
                        Fat16_Deinit();
2011
                        Fat16_Deinit();
2011
                        return(pVolumeLabel);
2012
                        return(pVolumeLabel);
2012
                }
2013
                }
2013
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2014
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2014
                // search all directory entries within that sector
2015
                // search all directory entries within that sector
2015
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2016
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2016
                {   // check for existing dir entry
2017
                {   // check for existing dir entry
2017
                        switch((u8)dir[dir_entry].Name[0])
2018
                        switch((u8)dir[dir_entry].Name[0])
2018
                        {
2019
                        {
2019
                                case SLOT_EMPTY:
2020
                                case SLOT_EMPTY:
2020
                                case SLOT_DELETED:
2021
                                case SLOT_DELETED:
2021
                                        // ignore empty or deleted dir entries
2022
                                        // ignore empty or deleted dir entries
2022
                                        break;
2023
                                        break;
2023
                                default:
2024
                                default:
2024
                                        // check attributes for volume label
2025
                                        // check attributes for volume label
2025
                                        if ((dir[dir_entry].Attribute & ATTR_VOLUMELABEL) != ATTR_VOLUMELABEL) break; // attribute must match
2026
                                        if ((dir[dir_entry].Attribute & ATTR_VOLUMELABEL) != ATTR_VOLUMELABEL) break; // attribute must match
2026
                                        // (first 11 characters include 8 chars of basename and 3 chars extension.)
2027
                                        // (first 11 characters include 8 chars of basename and 3 chars extension.)
2027
                                        for(i = 0; i<11;i++) Partition.VolumeLabel[i] = dir[dir_entry].Name[i];
2028
                                        for(i = 0; i<11;i++) Partition.VolumeLabel[i] = dir[dir_entry].Name[i];
2028
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2029
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2029
                                        file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
2030
                                        file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
2030
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
2031
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
2031
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2032
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2032
                                        file->SectorOfCurrCluster = 0;
2033
                                        file->SectorOfCurrCluster = 0;
2033
                                        file->ByteOfCurrSector = 0;
2034
                                        file->ByteOfCurrSector = 0;
2034
                                        file->DirectorySector = curr_sector; // current sector
2035
                                        file->DirectorySector = curr_sector; // current sector
2035
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2036
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2036
                                        file->Size = dir[dir_entry].Size;
2037
                                        file->Size = dir[dir_entry].Size;
2037
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2038
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2038
                                        pVolumeLabel =  Partition.VolumeLabel;
2039
                                        pVolumeLabel =  Partition.VolumeLabel;
2039
                        } // end of first byte of name check
2040
                        } // end of first byte of name check
2040
                }
2041
                }
2041
                dir_sector++; // search next sector
2042
                dir_sector++; // search next sector
2042
        // stop if we reached the end of the cluster or the end of the root dir
2043
        // stop if we reached the end of the cluster or the end of the root dir
2043
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2044
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2044
 
2045
 
2045
        UnlockFilePointer(file);
2046
        UnlockFilePointer(file);
2046
        return(pVolumeLabel);
2047
        return(pVolumeLabel);
2047
}
2048
}
2048
 
2049