Subversion Repositories NaviCtrl

Rev

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

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