Subversion Repositories NaviCtrl

Rev

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

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