Subversion Repositories NaviCtrl

Rev

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

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