Subversion Repositories NaviCtrl

Rev

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

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