Subversion Repositories NaviCtrl

Rev

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

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