Subversion Repositories NaviCtrl

Rev

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

Rev 359 Rev 360
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
-
 
6
// + Nur für den privaten Gebrauch / NON-COMMERCIAL USE ONLY
-
 
7
// + FOR NON COMMERCIAL USE ONLY
-
 
8
// + www.MikroKopter.com
5
// + www.MikroKopter.com
9
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
 
7
// + Software Nutzungsbedingungen (english version: see below)
10
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
8
// + der Fa. HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland - nachfolgend Lizenzgeber genannt -
11
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
9
// + Der Lizenzgeber räumt dem Kunden ein nicht-ausschließliches, zeitlich und räumlich* unbeschränktes Recht ein, die im den
12
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
10
// + Mikrocontroller verwendete Firmware für die Hardware Flight-Ctrl, Navi-Ctrl, BL-Ctrl, MK3Mag & PC-Programm MikroKopter-Tool 
13
// + bzgl. der Nutzungsbedingungen aufzunehmen.
11
// + - nachfolgend Software genannt - nur für private Zwecke zu nutzen.
14
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
12
// + Der Einsatz dieser Software ist nur auf oder mit Produkten des Lizenzgebers zulässig.
15
// + Verkauf von Luftbildaufnahmen, usw.
-
 
16
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
14
// + Die vom Lizenzgeber gelieferte Software ist urheberrechtlich geschützt. Alle Rechte an der Software sowie an sonstigen im
18
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
15
// + Rahmen der Vertragsanbahnung und Vertragsdurchführung überlassenen Unterlagen stehen im Verhältnis der Vertragspartner ausschließlich dem Lizenzgeber zu.
19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16
// + Die in der Software enthaltenen Copyright-Vermerke, Markenzeichen, andere Rechtsvorbehalte, Seriennummern sowie
20
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
17
// + sonstige der Programmidentifikation dienenden Merkmale dürfen vom Kunden nicht verändert oder unkenntlich gemacht werden.
21
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
18
// + Der Kunde trifft angemessene Vorkehrungen für den sicheren Einsatz der Software. Er wird die Software gründlich auf deren
22
// + eindeutig als Ursprung verlinkt werden
19
// + Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
23
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20
// + Die Haftung des Lizenzgebers wird - soweit gesetzlich zulässig - begrenzt in Höhe des typischen und vorhersehbaren
24
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
21
// + Schadens. Die gesetzliche Haftung bei Personenschäden und nach dem Produkthaftungsgesetz bleibt unberührt. Dem Lizenzgeber steht jedoch der Einwand 
25
// + Benutzung auf eigene Gefahr
22
// + des Mitverschuldens offen.
-
 
23
// + Der Kunde trifft angemessene Vorkehrungen für den Fall, dass die Software ganz oder teilweise nicht ordnungsgemäß arbeitet.
-
 
24
// + Er wird die Software gründlich auf deren Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
26
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
25
// + Der Kunde wird er seine Daten vor Einsatz der Software nach dem Stand der Technik sichern.
-
 
26
// + Der Kunde ist darüber unterrichtet, dass der Lizenzgeber seine Daten im zur Vertragsdurchführung erforderlichen Umfang
27
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27
// + und auf Grundlage der Datenschutzvorschriften erhebt, speichert, verarbeitet und, sofern notwendig, an Dritte übermittelt.
28
// + Die Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
28
// + *) Die räumliche Nutzung bezieht sich nur auf den Einsatzort, nicht auf die Reichweite der programmierten Software.
29
// + mit unserer Zustimmung zulässig
29
// + #### ENDE DER NUTZUNGSBEDINGUNGEN ####'
-
 
30
// +  Hinweis: Informationen über erweiterte Nutzungsrechte (wie z.B. Nutzung für nicht-private Zwecke) sind auf Anfrage per Email an info(@)hisystems.de verfügbar.
30
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
31
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
32
// + Software LICENSING TERMS
32
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
33
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
34
// + of HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland, Germany - the Licensor -
34
// + this list of conditions and the following disclaimer.
35
// + The Licensor grants the customer a non-exclusive license to use the microcontroller firmware of the Flight-Ctrl, Navi-Ctrl, BL-Ctrl, and MK3Mag hardware 
35
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
36
// + (the Software) exclusively for private purposes. The License is unrestricted with respect to time and territory*.
36
// +     from this software without specific prior written permission.
37
// + The Software may only be used with the Licensor's products.
37
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permitted
38
// + The Software provided by the Licensor is protected by copyright. With respect to the relationship between the parties to this
38
// +     for non-commercial use (directly or indirectly)
-
 
39
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
39
// + agreement, all rights pertaining to the Software and other documents provided during the preparation and execution of this
40
// +     with our written permission
40
// + agreement shall be the property of the Licensor.
41
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
41
// + The information contained in the Software copyright notices, trademarks, other legal reservations, serial numbers and other
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
42
// + features that can be used to identify the program may not be altered or defaced by the customer.
44
//
-
 
45
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43
// + The customer shall be responsible for taking reasonable precautions
46
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
// + for the safe use of the Software. The customer shall test the Software thoroughly regarding its suitability for the
47
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45
// + intended purpose before implementing it for actual operation. The Licensor's liability shall be limited to the extent of typical and
48
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
46
// + foreseeable damage to the extent permitted by law, notwithstanding statutory liability for bodily injury and product
49
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
47
// + liability. However, the Licensor shall be entitled to the defense of contributory negligence.
50
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
48
// + The customer will take adequate precautions in the case, that the software is not working properly. The customer will test
51
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49
// + the software for his purpose before any operational usage. The customer will backup his data before using the software.
52
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50
// + The customer understands that the Licensor collects, stores and processes, and, where required, forwards, customer data
53
// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
// + to third parties to the extent necessary for executing the agreement, subject to applicable data protection and privacy regulations.
54
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52
// + *) The territory aspect only refers to the place where the Software is used, not its programmed range.
55
// +  POSSIBILITY OF SUCH DAMAGE.
53
// + #### END OF LICENSING TERMS ####
-
 
54
// + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de.
56
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
55
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
57
#include <stdio.h>
56
#include <stdio.h>
58
#include <string.h>
57
#include <string.h>
59
#include "91x_lib.h"
58
#include "91x_lib.h"
60
#include "timer1.h"
59
#include "timer1.h"
61
#include "fat16.h"
60
#include "fat16.h"
62
#include "sdc.h"
61
#include "sdc.h"
63
#include "uart1.h"
62
#include "uart1.h"
64
 
63
 
65
//________________________________________________________________________________________________________________________________________
64
//________________________________________________________________________________________________________________________________________
66
// Module name:                 fat16.c
65
// Module name:                 fat16.c
67
// Compiler used:               avr-gcc 3.4.5
66
// Compiler used:               avr-gcc 3.4.5
68
// Last Modifikation:   20.03.2010
67
// Last Modifikation:   20.03.2010
69
// Version:                             2.10
68
// Version:                             2.10
70
// Authors:                             Stephan Busker & Gregor Stobrawa
69
// Authors:                             Stephan Busker & Gregor Stobrawa
71
// Description:                 Source files for FAT16 implementation with read and write-access
70
// Description:                 Source files for FAT16 implementation with read and write-access
72
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
71
//                                              Copyright (C) 2008 Stephan Busker & Gregor Stobrawa
73
//........................................................................................................................................
72
//........................................................................................................................................
74
// Functions:                   extern s16              Fat16_Init(void);
73
// Functions:                   extern s16              Fat16_Init(void);
75
//                                              extern s16              Fat16_Deinit(void);
74
//                                              extern s16              Fat16_Deinit(void);
76
//                                              extern s8*              FAT16_GetVolumeLabel(void);
75
//                                              extern s8*              FAT16_GetVolumeLabel(void);
77
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
76
//                                              extern File_t * fopen_(const u8 *filename, const s8 mode);
78
//                                              extern s16              fclose_(File_t *File);
77
//                                              extern s16              fclose_(File_t *File);
79
//                                              extern u8               fexist_(s8 * const filename);
78
//                                              extern u8               fexist_(s8 * const filename);
80
//                                              extern s16              fflush_(File_t *File);
79
//                                              extern s16              fflush_(File_t *File);
81
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
80
//                                              extern s16      fseek_(File_t *File, s32 offset, s16 origin);
82
//                                              extern s16              fgetc_(File_t *File);
81
//                                              extern s16              fgetc_(File_t *File);
83
//                                              extern s16              fputc_(u8 c, File_t *File);
82
//                                              extern s16              fputc_(u8 c, File_t *File);
84
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File);
83
//                                              extern u32              fread_(void *buffer, u32 size, u32 count, File_t *File);
85
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
84
//                                              extern u32              fwrite_(void *buffer, u32 size, u32 count, File_t *File);
86
//                                              extern s16              fputs_(const u8 *string, File_t *File);
85
//                                              extern s16              fputs_(const u8 *string, File_t *File);
87
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
86
//                                              extern u8 *     fgets_(u8 *string, s16 length, File_t *File);
88
//                                              extern u8               feof_(File_t * const file);
87
//                                              extern u8               feof_(File_t * const file);
89
//........................................................................................................................................
88
//........................................................................................................................................
90
// ext. functions:              extern SD_Result_t SDC_Init(void;)
89
// ext. functions:              extern SD_Result_t SDC_Init(void;)
91
//                                              extern SD_Result_t SDC_Deinit(void);
90
//                                              extern SD_Result_t SDC_Deinit(void);
92
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);
91
//                      extern SD_Result_t SDC_GetSector (u32,u8 *);
93
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
92
//                                              extern SD_Result_t SDC_PutSector (u32,u8 *);
94
//........................................................................................................................................
93
//........................................................................................................................................
95
//
94
//
96
// URL:                                 www.Mikro-Control.de
95
// URL:                                 www.Mikro-Control.de
97
// mailto:                              stephan.busker@mikro-control.de
96
// mailto:                              stephan.busker@mikro-control.de
98
//________________________________________________________________________________________________________________________________________
97
//________________________________________________________________________________________________________________________________________
99
 
98
 
100
/*
99
/*
101
FAT16 Drive Layout:
100
FAT16 Drive Layout:
102
Description                                             Offset
101
Description                                             Offset
103
Volume Boot Sector                                      Start of Partition
102
Volume Boot Sector                                      Start of Partition
104
Fat Tables                                                      Start + # of Reserved Sectors
103
Fat Tables                                                      Start + # of Reserved Sectors
105
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
104
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
106
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
105
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
107
*/
106
*/
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
 
325
 
324
 
326
 
325
 
327
 
326
 
328
/****************************************************************************************************************************************/
327
/****************************************************************************************************************************************/
329
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
328
/*      Function:               FileDate(DateTime_t *);                                                                                                                                                                                         */
330
/*                                                                                                                                                                                                                                                                              */
329
/*                                                                                                                                                                                                                                                                              */
331
/*      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.                                                                                       */
332
/*                                                                                                                                                                                                                                                                              */
331
/*                                                                                                                                                                                                                                                                              */
333
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
332
/*      Returnvalue:    Returns the DOS date.                                                                                                                                                                                           */
334
/****************************************************************************************************************************************/
333
/****************************************************************************************************************************************/
335
u16 FileDate(DateTime_t * pTimeStruct)
334
u16 FileDate(DateTime_t * pTimeStruct)
336
{
335
{
337
        u16 date = 0;
336
        u16 date = 0;
338
        if(pTimeStruct == NULL)   return date;
337
        if(pTimeStruct == NULL)   return date;
339
        if(!(pTimeStruct->Valid)) return date;
338
        if(!(pTimeStruct->Valid)) return date;
340
 
339
 
341
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
340
        date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year
342
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
341
        date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month
343
        date |= (0x001F & (u16)(pTimeStruct->Day));
342
        date |= (0x001F & (u16)(pTimeStruct->Day));
344
        return date;
343
        return date;
345
}
344
}
346
 
345
 
347
/****************************************************************************************************************************************/
346
/****************************************************************************************************************************************/
348
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
347
/*      Function:               FileTime(DateTime_t *);                                                                                                                                                                                         */
349
/*                                                                                                                                                                                                                                                                              */
348
/*                                                                                                                                                                                                                                                                              */
350
/*      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.                                                                                       */
351
/*                                                                                                                                                                                                                                                                              */
350
/*                                                                                                                                                                                                                                                                              */
352
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
351
/*      Returnvalue:    Returns the DOS time.                                                                                                                                                                                           */
353
/****************************************************************************************************************************************/
352
/****************************************************************************************************************************************/
354
 
353
 
355
u16 FileTime(DateTime_t * pTimeStruct)
354
u16 FileTime(DateTime_t * pTimeStruct)
356
{
355
{
357
        u16 time = 0;
356
        u16 time = 0;
358
        if(pTimeStruct == NULL)   return time;
357
        if(pTimeStruct == NULL)   return time;
359
        if(!(pTimeStruct->Valid)) return time;
358
        if(!(pTimeStruct->Valid)) return time;
360
 
359
 
361
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
360
        time |= (0x001F & (u16)(pTimeStruct->Hour))<<11;
362
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
361
        time |= (0x003F & (u16)(pTimeStruct->Min))<<5;
363
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
362
        time |= (0x001F & (u16)(pTimeStruct->Sec/2));
364
        return time;
363
        return time;
365
}
364
}
366
 
365
 
367
/****************************************************************************************************************************************/
366
/****************************************************************************************************************************************/
368
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
367
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
369
/*                                                                                                                                                                                                                                                                              */
368
/*                                                                                                                                                                                                                                                                              */
370
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
369
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
371
/*                                                                                                                                                                                                                                                                              */
370
/*                                                                                                                                                                                                                                                                              */
372
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
371
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
373
/****************************************************************************************************************************************/
372
/****************************************************************************************************************************************/
374
File_t * LockFilePointer(void)
373
File_t * LockFilePointer(void)
375
{
374
{
376
        u8 i;
375
        u8 i;
377
        File_t * File = 0;
376
        File_t * File = 0;
378
        for(i = 0; i < FILE_MAX_OPEN; i++)
377
        for(i = 0; i < FILE_MAX_OPEN; i++)
379
        {
378
        {
380
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one
379
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one
381
                {
380
                {
382
                        File = &FilePointer[i];                                         // set pointer to that entry
381
                        File = &FilePointer[i];                                         // set pointer to that entry
383
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
382
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
384
                        break;
383
                        break;
385
                }
384
                }
386
        }
385
        }
387
        return(File);
386
        return(File);
388
}
387
}
389
 
388
 
390
/****************************************************************************************************************************************/
389
/****************************************************************************************************************************************/
391
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
390
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
392
/*                                                                                                                                                                                                                                                                              */
391
/*                                                                                                                                                                                                                                                                              */
393
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
392
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
394
/*                                                                                                                                                                                                                                                                              */
393
/*                                                                                                                                                                                                                                                                              */
395
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
394
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
396
/****************************************************************************************************************************************/
395
/****************************************************************************************************************************************/
397
u8 UnlockFilePointer(File_t * file)
396
u8 UnlockFilePointer(File_t * file)
398
{
397
{
399
        u8 cnt;
398
        u8 cnt;
400
        if(file == NULL) return(0);
399
        if(file == NULL) return(0);
401
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
400
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
402
        {
401
        {
403
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
402
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
404
                {
403
                {
405
                        file->State = FSTATE_UNUSED;
404
                        file->State = FSTATE_UNUSED;
406
                        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.
407
                        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.
408
                        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).
409
                        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).
410
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
409
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
411
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
410
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
412
                        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
413
                        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.
414
                        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.
415
                        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.
416
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
415
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
417
                        file = NULL;
416
                        file = NULL;
418
                        return(1);
417
                        return(1);
419
                }
418
                }
420
        }
419
        }
421
        return(0);
420
        return(0);
422
}
421
}
423
 
422
 
424
/****************************************************************************************************************************************/
423
/****************************************************************************************************************************************/
425
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
424
/*      Function:               SeperateDirName(s8*, s8*);                                                                                                                                                                              */
426
/*                                                                                                                                                                                                                                                                              */
425
/*                                                                                                                                                                                                                                                                              */
427
/*      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                                                                                         */
428
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
427
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
429
/*                                      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                                                                                           */
430
/*                                                                                                                                                                                                                                                                              */
429
/*                                                                                                                                                                                                                                                                              */
431
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
430
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
432
/****************************************************************************************************************************************/
431
/****************************************************************************************************************************************/
433
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
432
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
434
{
433
{
435
        s8* subpath = NULL;
434
        s8* subpath = NULL;
436
        u8 readpointer  = 0;
435
        u8 readpointer  = 0;
437
        u8 writepointer = 0;
436
        u8 writepointer = 0;
438
 
437
 
439
        // search subpath from beginning of filepath
438
        // search subpath from beginning of filepath
440
        subpath = NULL;
439
        subpath = NULL;
441
        readpointer     = 0;
440
        readpointer     = 0;
442
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
441
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
443
        while(subpath == NULL)  // search the filepath until a subpath was found.
442
        while(subpath == NULL)  // search the filepath until a subpath was found.
444
        {
443
        {
445
                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
446
                {
445
                {
447
                        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
448
                }
447
                }
449
                readpointer++;
448
                readpointer++;
450
        }
449
        }
451
 
450
 
452
        // clear dirname with spaces
451
        // clear dirname with spaces
453
        dirname[11] = 0; // terminate dirname
452
        dirname[11] = 0; // terminate dirname
454
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
453
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
455
 
454
 
456
        // handle the special dirnames "." and ".." seperately
455
        // handle the special dirnames "." and ".." seperately
457
        readpointer = 0;
456
        readpointer = 0;
458
        if(filepath[0] == '/') readpointer++;
457
        if(filepath[0] == '/') readpointer++;
459
        // if we are trying to enter directories "." or ".." 
458
        // if we are trying to enter directories "." or ".." 
460
        if(filepath[readpointer] == '.')
459
        if(filepath[readpointer] == '.')
461
        {
460
        {
462
                // directory '.'
461
                // directory '.'
463
                if(filepath[readpointer+1] == 0)
462
                if(filepath[readpointer+1] == 0)
464
                {
463
                {
465
                        dirname[0] = '.';
464
                        dirname[0] = '.';
466
                        return((s8*)&filepath[readpointer]);
465
                        return((s8*)&filepath[readpointer]);
467
                }
466
                }
468
                // directory '..'               
467
                // directory '..'               
469
                if((filepath[readpointer+1] == '.') &&  (filepath[readpointer+2] == 0))
468
                if((filepath[readpointer+1] == '.') &&  (filepath[readpointer+2] == 0))
470
                {
469
                {
471
                        dirname[0] = '.';
470
                        dirname[0] = '.';
472
                        dirname[1] = '.';
471
                        dirname[1] = '.';
473
                        return((s8*)&filepath[readpointer]);
472
                        return((s8*)&filepath[readpointer]);
474
                }
473
                }
475
        }
474
        }
476
 
475
 
477
        writepointer = 0;
476
        writepointer = 0;
478
        // start seperating the dirname from the filepath.
477
        // start seperating the dirname from the filepath.
479
        readpointer = 0;
478
        readpointer = 0;
480
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
479
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
481
        while( &filepath[readpointer] < subpath)
480
        while( &filepath[readpointer] < subpath)
482
        {
481
        {
483
                if(writepointer >= 11) return(NULL);            // dirname to long
482
                if(writepointer >= 11) return(NULL);            // dirname to long
484
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
483
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
485
                {
484
                {
486
                        if(writepointer <= 8)
485
                        if(writepointer <= 8)
487
                        {
486
                        {
488
                                readpointer++;                                          // next character in filename
487
                                readpointer++;                                          // next character in filename
489
                                writepointer = 8;                                       // jump to start of extension
488
                                writepointer = 8;                                       // jump to start of extension
490
                        }
489
                        }
491
                        else return(NULL);                                              // dirbasename to long
490
                        else return(NULL);                                              // dirbasename to long
492
                }
491
                }
493
                else
492
                else
494
                {
493
                {
495
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
494
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
496
                        {
495
                        {
497
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
496
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
498
                        }
497
                        }
499
                        else
498
                        else
500
                        {
499
                        {
501
                                dirname[writepointer] = filepath[readpointer];
500
                                dirname[writepointer] = filepath[readpointer];
502
                        }
501
                        }
503
                        readpointer++;
502
                        readpointer++;
504
                        writepointer++;
503
                        writepointer++;
505
                }
504
                }
506
        }
505
        }
507
        return(subpath);
506
        return(subpath);
508
}
507
}
509
 
508
 
510
 
509
 
511
/**************************************************************************************************************************************+*/
510
/**************************************************************************************************************************************+*/
512
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
511
/*      Function:       Fat16ClusterToSector( u16 cluster);                                                                                                                                                                             */
513
/*                                                                                                                                                                                                                                                                              */
512
/*                                                                                                                                                                                                                                                                              */
514
/*      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                                                                           */
515
/*                                      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.                                                     */
516
/*                                                                                                                                                                                                                                                                              */
515
/*                                                                                                                                                                                                                                                                              */
517
/*      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                                                                                                                          */
518
/****************************************************************************************************************************************/
517
/****************************************************************************************************************************************/
519
u32     Fat16ClusterToSector(u16 cluster)
518
u32     Fat16ClusterToSector(u16 cluster)
520
{
519
{
521
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
520
        if(!Partition.IsValid) return SECTOR_UNDEFINED;
522
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
521
        if ((cluster < 2) || (cluster == CLUSTER_UNDEFINED))
523
        {
522
        {
524
                return SECTOR_UNDEFINED;
523
                return SECTOR_UNDEFINED;
525
        }
524
        }
526
        else
525
        else
527
        {
526
        {
528
                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
529
        }
528
        }
530
}
529
}
531
 
530
 
532
/****************************************************************************************************************************************/
531
/****************************************************************************************************************************************/
533
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
532
/*      Function:       SectorToFat16Cluster( u32 sector);                                                                                                                                                                              */
534
/*                                                                                                                                                                                                                                                                              */
533
/*                                                                                                                                                                                                                                                                              */
535
/*      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                                                                                         */
536
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
535
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
537
/*                                                                                                                                                                                                                                                                              */
536
/*                                                                                                                                                                                                                                                                              */
538
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
537
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
539
/****************************************************************************************************************************************/
538
/****************************************************************************************************************************************/
540
u16     SectorToFat16Cluster(u32 sector)
539
u16     SectorToFat16Cluster(u32 sector)
541
{
540
{
542
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
541
        if(!Partition.IsValid) return CLUSTER_UNDEFINED;
543
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
542
        if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED;
544
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
543
        else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
545
}
544
}
546
 
545
 
547
 
546
 
548
/****************************************************************************************************************************************/
547
/****************************************************************************************************************************************/
549
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
548
/*      Function:       Fat16_IsValid(void);                                                                                                                                                                                                    */
550
/*                                                                                                                                                                                                                                                                              */
549
/*                                                                                                                                                                                                                                                                              */
551
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
550
/*      Description:    This function return the Fat 16 filesystem state                                                                                                                                        */
552
/*                                                                                                                                                                                                                                                                              */
551
/*                                                                                                                                                                                                                                                                              */
553
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
552
/*      Returnvalue: The function returns "1" on success                                                                                                                                                                        */
554
/****************************************************************************************************************************************/
553
/****************************************************************************************************************************************/
555
u8 Fat16_IsValid(void)
554
u8 Fat16_IsValid(void)
556
{
555
{
557
        return(Partition.IsValid);
556
        return(Partition.IsValid);
558
}
557
}
559
 
558
 
560
/****************************************************************************************************************************************/
559
/****************************************************************************************************************************************/
561
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
560
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
562
/*                                                                                                                                                                                                                                                                              */
561
/*                                                                                                                                                                                                                                                                              */
563
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
562
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
564
/*                                                                                                                                                                                                                                                                              */
563
/*                                                                                                                                                                                                                                                                              */
565
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
564
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
566
/****************************************************************************************************************************************/
565
/****************************************************************************************************************************************/
567
u8 Fat16_Deinit(void)
566
u8 Fat16_Deinit(void)
568
{
567
{
569
        s16 returnvalue = 0;
568
        s16 returnvalue = 0;
570
        u8 cnt;
569
        u8 cnt;
571
 
570
 
572
        UART1_PutString("\r\n FAT16 deinit...");
571
        UART1_PutString("\r\n FAT16 deinit...");
573
        // declare the filepointers as unused.
572
        // declare the filepointers as unused.
574
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
573
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
575
        {      
574
        {      
576
                UnlockFilePointer(&FilePointer[cnt]);
575
                UnlockFilePointer(&FilePointer[cnt]);
577
        }
576
        }
578
        returnvalue = SDC_Deinit();                     // uninitialize interface to sd-card
577
        returnvalue = SDC_Deinit();                     // uninitialize interface to sd-card
579
        Partition.IsValid = 0;  // mark data in partition structure as invalid
578
        Partition.IsValid = 0;  // mark data in partition structure as invalid
580
        Partition.VolumeLabel[0]='\0';
579
        Partition.VolumeLabel[0]='\0';
581
        UART1_PutString("ok");
580
        UART1_PutString("ok");
582
        return(returnvalue);
581
        return(returnvalue);
583
}
582
}
584
 
583
 
585
/****************************************************************************************************************************************/
584
/****************************************************************************************************************************************/
586
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
585
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
587
/*                                                                                                                                                                                                                                                                          */
586
/*                                                                                                                                                                                                                                                                          */
588
/*      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    */
589
/*                                      and stores the information in global variables.                                                                                                                                     */
588
/*                                      and stores the information in global variables.                                                                                                                                     */
590
/*                                                                                                                                                                                                                                                                          */
589
/*                                                                                                                                                                                                                                                                          */
591
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
590
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
592
/****************************************************************************************************************************************/
591
/****************************************************************************************************************************************/
593
u8 Fat16_Init(void)
592
u8 Fat16_Init(void)
594
{
593
{
595
    u8  cnt     = 0;
594
    u8  cnt     = 0;
596
        u32     partitionfirstsector;
595
        u32     partitionfirstsector;
597
        VBR_Entry_t *VBR;
596
        VBR_Entry_t *VBR;
598
        MBR_Entry_t *MBR;
597
        MBR_Entry_t *MBR;
599
        File_t *file;
598
        File_t *file;
600
        u8 result = 0;
599
        u8 result = 0;
601
 
600
 
602
        UART1_PutString("\r\n FAT16 init...");
601
        UART1_PutString("\r\n FAT16 init...");
603
        Partition.IsValid = 0;
602
        Partition.IsValid = 0;
604
        // declare the filepointers as unused.
603
        // declare the filepointers as unused.
605
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
604
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
606
        {
605
        {
607
                UnlockFilePointer(&FilePointer[cnt]);
606
                UnlockFilePointer(&FilePointer[cnt]);
608
        }
607
        }
609
        // set current file pinter to first position in list
608
        // set current file pinter to first position in list
610
        file = &FilePointer[0];
609
        file = &FilePointer[0];
611
 
610
 
612
        // try to initialize the sd-card.
611
        // try to initialize the sd-card.
613
        if(SD_SUCCESS != SDC_Init())
612
        if(SD_SUCCESS != SDC_Init())
614
        {
613
        {
615
                UART1_PutString("SD-Card could not be initialized.");
614
                UART1_PutString("SD-Card could not be initialized.");
616
                result = 1;
615
                result = 1;
617
                goto end;
616
                goto end;
618
        }
617
        }
619
 
618
 
620
        // SD-Card is initialized successfully
619
        // SD-Card is initialized successfully
621
        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
622
        {
621
        {
623
                UART1_PutString("Error reading the MBR.");
622
                UART1_PutString("Error reading the MBR.");
624
                result = 2;
623
                result = 2;
625
                goto end;
624
                goto end;
626
        }
625
        }
627
        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.
628
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
627
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
629
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
628
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
630
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
629
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
631
        {
630
        {
632
                // get sector offset 1st partition
631
                // get sector offset 1st partition
633
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
632
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
634
                // Start of Partition is the Volume Boot Sector
633
                // Start of Partition is the Volume Boot Sector
635
                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
636
                {
635
                {
637
                        UART1_PutString("Error reading the VBR.");
636
                        UART1_PutString("Error reading the VBR.");
638
                        result = 3;
637
                        result = 3;
639
                        goto end;
638
                        goto end;
640
                }
639
                }
641
        }
640
        }
642
        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
643
        {
642
        {
644
                partitionfirstsector = 0;
643
                partitionfirstsector = 0;
645
        }
644
        }
646
 
645
 
647
        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.
648
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
647
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
649
        {
648
        {
650
                UART1_PutString("VBR: Sector size not supported.");
649
                UART1_PutString("VBR: Sector size not supported.");
651
                result = 4;
650
                result = 4;
652
                goto end;
651
                goto end;
653
        }
652
        }
654
        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.
655
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
654
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
656
        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).
657
        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
658
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
657
        Partition.VolumeLabel[0] = '\0';                                                                        // set string terminator
659
 
658
 
660
        /* 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. */
661
        // Calculate the position of the FileAllocationTable:
660
        // Calculate the position of the FileAllocationTable:
662
        // Start + # of Reserved Sectors
661
        // Start + # of Reserved Sectors
663
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
662
        Partition.FirstFatSector        =   (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
664
        // Calculate the position of the Rootdirectory:
663
        // Calculate the position of the Rootdirectory:
665
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
664
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
666
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
665
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
667
        // Calculate the position of the first datacluster:
666
        // Calculate the position of the first datacluster:
668
        // 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)
669
        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
670
        // Calculate the last data sector
669
        // Calculate the last data sector
671
        if(VBR->NoSectors == 0)
670
        if(VBR->NoSectors == 0)
672
        {
671
        {
673
                UART1_PutString("VBR: Bad number of sectors.");
672
                UART1_PutString("VBR: Bad number of sectors.");
674
                result = 5;
673
                result = 5;
675
                goto end;
674
                goto end;
676
        }
675
        }
677
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
676
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
678
        // check for FAT16 in VBR of first partition
677
        // check for FAT16 in VBR of first partition
679
        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')))
680
        {
679
        {
681
                UART1_PutString("VBR: Partition ist not FAT16 type.");
680
                UART1_PutString("VBR: Partition ist not FAT16 type.");
682
                result = 6;
681
                result = 6;
683
                goto end;
682
                goto end;
684
        }
683
        }
685
        Partition.IsValid = 1; // mark data in partition structure as valid
684
        Partition.IsValid = 1; // mark data in partition structure as valid
686
        Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
685
        Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
687
        strcpy(Partition.PathToCwd,"/");       
686
        strcpy(Partition.PathToCwd,"/");       
688
        result = 0;
687
        result = 0;
689
        end:
688
        end:
690
        if(result != 0) Fat16_Deinit();
689
        if(result != 0) Fat16_Deinit();
691
        else UART1_PutString("ok");
690
        else UART1_PutString("ok");
692
        return(result);
691
        return(result);
693
}
692
}
694
 
693
 
695
 
694
 
696
 
695
 
697
/****************************************************************************************************************************************/
696
/****************************************************************************************************************************************/
698
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
697
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
699
/*                                                                                                                                                                                                                                                                              */
698
/*                                                                                                                                                                                                                                                                              */
700
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
699
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
701
/*                                                                                                                                                                                                                                                                              */
700
/*                                                                                                                                                                                                                                                                              */
702
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
701
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
703
/****************************************************************************************************************************************/
702
/****************************************************************************************************************************************/
704
u8 ClearCurrCluster(File_t * file)
703
u8 ClearCurrCluster(File_t * file)
705
{
704
{
706
        u8 retvalue = 1;
705
        u8 retvalue = 1;
707
        u32 i;
706
        u32 i;
708
 
707
 
709
        if((!Partition.IsValid) || (file == NULL)) return(0);
708
        if((!Partition.IsValid) || (file == NULL)) return(0);
710
 
709
 
711
        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
712
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do 
711
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do 
713
        for(i = 0; i < Partition.SectorsPerCluster; i++)
712
        for(i = 0; i < Partition.SectorsPerCluster; i++)
714
        {
713
        {
715
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
714
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
716
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
715
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
717
                {
716
                {
718
                        Fat16_Deinit();
717
                        Fat16_Deinit();
719
                        retvalue = 0;
718
                        retvalue = 0;
720
                        return(retvalue);
719
                        return(retvalue);
721
                }
720
                }
722
        }
721
        }
723
        return(retvalue);
722
        return(retvalue);
724
}
723
}
725
 
724
 
726
/*****************************************************************************************************************************************/
725
/*****************************************************************************************************************************************/
727
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
726
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
728
/*                                                                                                                                                                                                                                                                               */
727
/*                                                                                                                                                                                                                                                                               */
729
/* 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.                                                                                  */
730
/*                                                                                                                                                                                                                                                                               */
729
/*                                                                                                                                                                                                                                                                               */
731
/* 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.                                                                                                      */
732
/*****************************************************************************************************************************************/
731
/*****************************************************************************************************************************************/
733
u16 GetNextCluster(File_t * file)
732
u16 GetNextCluster(File_t * file)
734
{
733
{
735
        u16 cluster = CLUSTER_UNDEFINED;
734
        u16 cluster = CLUSTER_UNDEFINED;
736
        u32 fat_byte_offset, sector, byte;
735
        u32 fat_byte_offset, sector, byte;
737
        Fat16Entry_t * fat;
736
        Fat16Entry_t * fat;
738
 
737
 
739
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
738
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
740
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
739
        if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster);
741
        // if sector is within the data area
740
        // if sector is within the data area
742
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
741
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
743
        {
742
        {
744
                // determine current file cluster
743
                // determine current file cluster
745
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
744
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
746
                // calculate byte offset in the fat for corresponding entry
745
                // calculate byte offset in the fat for corresponding entry
747
                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
748
                // calculate the sector that contains the current cluster within the fat
747
                // calculate the sector that contains the current cluster within the fat
749
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
748
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
750
                // calculate byte offset of the current cluster within that fat sector
749
                // calculate byte offset of the current cluster within that fat sector
751
                byte = fat_byte_offset % BYTES_PER_SECTOR;
750
                byte = fat_byte_offset % BYTES_PER_SECTOR;
752
                // read this sector to the file cache
751
                // read this sector to the file cache
753
                if(file->SectorInCache != sector)
752
                if(file->SectorInCache != sector)
754
                {
753
                {
755
                        file->SectorInCache = sector;                                           // update sector stored in buffer
754
                        file->SectorInCache = sector;                                           // update sector stored in buffer
756
                        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
757
                        {
756
                        {
758
                                Fat16_Deinit();
757
                                Fat16_Deinit();
759
                                return (cluster);
758
                                return (cluster);
760
                        }
759
                        }
761
                }
760
                }
762
                // read the next cluster from cache
761
                // read the next cluster from cache
763
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
762
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
764
                cluster = fat->NextCluster;
763
                cluster = fat->NextCluster;
765
                // if no next cluster exist
764
                // if no next cluster exist
766
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
765
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
767
                {
766
                {
768
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
767
                         cluster = CLUSTER_UNDEFINED; // next cluster is undefined
769
                }
768
                }
770
                else
769
                else
771
                {
770
                {
772
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
771
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
773
                        file->SectorOfCurrCluster = 0;
772
                        file->SectorOfCurrCluster = 0;
774
                        file->ByteOfCurrSector = 0;
773
                        file->ByteOfCurrSector = 0;
775
                }
774
                }
776
        }
775
        }
777
        return(cluster);
776
        return(cluster);
778
}
777
}
779
 
778
 
780
 
779
 
781
 
780
 
782
/****************************************************************************************************************************************/
781
/****************************************************************************************************************************************/
783
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
782
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
784
/*                                                                                                                                                                                                                                                                              */
783
/*                                                                                                                                                                                                                                                                              */
785
/* 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                                                                                                                    */
786
/*                                                                                                                                                                                                                                                                              */
785
/*                                                                                                                                                                                                                                                                              */
787
/* 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.                                                                  */
788
/****************************************************************************************************************************************/
787
/****************************************************************************************************************************************/
789
u16 FindNextFreeCluster(File_t *file)
788
u16 FindNextFreeCluster(File_t *file)
790
{
789
{
791
        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.
792
        u32     curr_sector;                            // current sector
791
        u32     curr_sector;                            // current sector
793
        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).
794
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
793
        u16     free_cluster    = CLUSTER_UNDEFINED;    // next free cluster number.
795
        Fat16Entry_t * fat;
794
        Fat16Entry_t * fat;
796
 
795
 
797
        if((!Partition.IsValid) || (file == NULL)) return(0);
796
        if((!Partition.IsValid) || (file == NULL)) return(0);
798
 
797
 
799
        // 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.
800
        fat_sector = 0;
799
        fat_sector = 0;
801
        do
800
        do
802
        {
801
        {
803
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
802
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
804
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
803
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
805
                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.
806
                {
805
                {
807
                        Fat16_Deinit();
806
                        Fat16_Deinit();
808
                        return(free_cluster);
807
                        return(free_cluster);
809
                }
808
                }
810
 
809
 
811
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
810
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
812
 
811
 
813
                for(fat_entry = 0; fat_entry < FAT16_ENTRIES_PER_SECTOR; fat_entry++)                                           // look for an free cluster at all entries in this sector of the fat.
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.
814
                {
813
                {
815
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
814
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
816
                        {
815
                        {
817
                                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
818
                                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.
819
                                {
818
                                {
820
                                        Fat16_Deinit();
819
                                        Fat16_Deinit();
821
                                        return(free_cluster);
820
                                        return(free_cluster);
822
                                }
821
                                }
823
                                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);
824
                                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.
825
                        }
824
                        }
826
                }
825
                }
827
                fat_sector++;                                                                                                   // continue the search in next fat sector
826
                fat_sector++;                                                                                                   // continue the search in next fat sector
828
        // 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
829
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
828
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
830
        return(free_cluster);
829
        return(free_cluster);
831
}
830
}
832
 
831
 
833
 
832
 
834
/****************************************************************************************************************************************************/
833
/****************************************************************************************************************************************************/
835
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
834
/* Function:    s16 fseek_(File_t *, s32 *, u8)                                                                                                                                                                                                         */
836
/*                                                                                                                                                                                                                                                                                                      */
835
/*                                                                                                                                                                                                                                                                                                      */
837
/* 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                                                                                                                           */
838
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
837
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
839
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                                                                     */
838
/* Returnvalue: Is 0 if seek was successful                                                                                                                                                                                                                                                                     */
840
/****************************************************************************************************************************************************/
839
/****************************************************************************************************************************************************/
841
s16 fseek_(File_t *file, s32 offset, s16 origin)
840
s16 fseek_(File_t *file, s32 offset, s16 origin)
842
{
841
{
843
        s32             fposition       = 0;
842
        s32             fposition       = 0;
844
        s16     retvalue        = 1;
843
        s16     retvalue        = 1;
845
 
844
 
846
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
845
        if((!Partition.IsValid) || (file == NULL)) return(retvalue);
847
        switch(origin)
846
        switch(origin)
848
        {
847
        {
849
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
848
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
850
                        fposition = 0;
849
                        fposition = 0;
851
                        break;
850
                        break;
852
                case SEEK_END:                          // Fileposition relative to the end of the file.
851
                case SEEK_END:                          // Fileposition relative to the end of the file.
853
                        fposition = (s32)file->Size;
852
                        fposition = (s32)file->Size;
854
                        break;
853
                        break;
855
                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.
856
                default:
855
                default:
857
                        fposition = file->Position;
856
                        fposition = file->Position;
858
                        break;
857
                        break;
859
        }
858
        }
860
 
859
 
861
        fposition += offset;
860
        fposition += offset;
862
 
861
 
863
        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?
864
        {
863
        {
865
                // reset file position to start of the file
864
                // reset file position to start of the file
866
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
865
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
867
                file->SectorOfCurrCluster       = 0;
866
                file->SectorOfCurrCluster       = 0;
868
                file->ByteOfCurrSector          = 0;
867
                file->ByteOfCurrSector          = 0;
869
                file->Position                          = 0;
868
                file->Position                          = 0;
870
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
869
                if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue);
871
                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
872
                {
871
                {
873
                        file->Position++;                               // increment file position
872
                        file->Position++;                               // increment file position
874
                        file->ByteOfCurrSector++;               // next byte in current sector
873
                        file->ByteOfCurrSector++;               // next byte in current sector
875
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
874
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
876
                        {
875
                        {
877
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
876
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
878
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
877
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
879
                                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.
880
                                {
879
                                {
881
                                        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.
882
                                        {
881
                                        {
883
                                                file->SectorOfCurrCluster = 0;
882
                                                file->SectorOfCurrCluster = 0;
884
                                        }
883
                                        }
885
                                        else // the last cluster was allready reached
884
                                        else // the last cluster was allready reached
886
                                        {
885
                                        {
887
                                                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
888
                                                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
889
                                        }
888
                                        }
890
                                }
889
                                }
891
                        }
890
                        }
892
                }
891
                }
893
        }
892
        }
894
        if(file->Position == fposition) retvalue = 0;
893
        if(file->Position == fposition) retvalue = 0;
895
        return(retvalue);
894
        return(retvalue);
896
}
895
}
897
 
896
 
898
 
897
 
899
/****************************************************************************************************************************************/
898
/****************************************************************************************************************************************/
900
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
899
/* Function:    u16 DeleteClusterChain(File *file);                                                                                                                                                                             */
901
/*                                                                                                                                                                                                                                                                              */
900
/*                                                                                                                                                                                                                                                                              */
902
/* 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.                                                                  */
903
/*                                                                                                                                                                                                                                                                              */
902
/*                                                                                                                                                                                                                                                                              */
904
/****************************************************************************************************************************************/
903
/****************************************************************************************************************************************/
905
u8 DeleteClusterChain(u16 StartCluster)
904
u8 DeleteClusterChain(u16 StartCluster)
906
{
905
{
907
        u16 cluster;
906
        u16 cluster;
908
        u32 fat_byte_offset, sector, byte;
907
        u32 fat_byte_offset, sector, byte;
909
        Fat16Entry_t * fat;
908
        Fat16Entry_t * fat;
910
        u8 buffer[BYTES_PER_SECTOR];
909
        u8 buffer[BYTES_PER_SECTOR];
911
        u32 sector_in_buffer = 0;
910
        u32 sector_in_buffer = 0;
912
        u8 repeat = 0;
911
        u8 repeat = 0;
913
 
912
 
914
        if(!Partition.IsValid) return(0);
913
        if(!Partition.IsValid) return(0);
915
        if(StartCluster == CLUSTER_UNDEFINED) return(0);
914
        if(StartCluster == CLUSTER_UNDEFINED) return(0);
916
        cluster = StartCluster; // init chain trace
915
        cluster = StartCluster; // init chain trace
917
        // if start cluster is no real cluster
916
        // if start cluster is no real cluster
918
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1;
917
    if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1;
919
 
918
 
920
        // calculate byte offset in the fat for corresponding entry
919
        // calculate byte offset in the fat for corresponding entry
921
        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
922
        // calculate the sector that contains the current cluster within the fat
921
        // calculate the sector that contains the current cluster within the fat
923
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
922
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
924
        // calculate byte offset of the current cluster within that fat sector
923
        // calculate byte offset of the current cluster within that fat sector
925
        byte = fat_byte_offset % BYTES_PER_SECTOR;
924
        byte = fat_byte_offset % BYTES_PER_SECTOR;
926
        do
925
        do
927
        {
926
        {
928
                if(sector != sector_in_buffer)
927
                if(sector != sector_in_buffer)
929
                {
928
                {
930
                        // read this sector to buffer
929
                        // read this sector to buffer
931
                        sector_in_buffer = sector;
930
                        sector_in_buffer = sector;
932
                        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
933
                }
932
                }
934
                // read the next cluster from cache
933
                // read the next cluster from cache
935
                fat = (Fat16Entry_t *)(&(buffer[byte]));
934
                fat = (Fat16Entry_t *)(&(buffer[byte]));
936
                cluster = fat->NextCluster;
935
                cluster = fat->NextCluster;
937
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
936
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
938
 
937
 
939
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
938
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) )
940
                {
939
                {
941
                        repeat = 1;
940
                        repeat = 1;
942
                        // 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
943
                        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
944
                        // calculate the sector that contains the current cluster within the fat
943
                        // calculate the sector that contains the current cluster within the fat
945
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
944
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
946
                        // calculate byte offset of the current cluster within that fat sector
945
                        // calculate byte offset of the current cluster within that fat sector
947
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
946
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
948
                }
947
                }
949
                else repeat = 0;
948
                else repeat = 0;
950
 
949
 
951
                // 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
952
                if((sector != sector_in_buffer) || !repeat)
951
                if((sector != sector_in_buffer) || !repeat)
953
                {       // write sector in buffer
952
                {       // write sector in buffer
954
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
953
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer))
955
                        {
954
                        {
956
                                Fat16_Deinit();
955
                                Fat16_Deinit();
957
                                return(0);
956
                                return(0);
958
                        }
957
                        }
959
                }
958
                }
960
        }
959
        }
961
        while(repeat);
960
        while(repeat);
962
 
961
 
963
        return 1;
962
        return 1;
964
}
963
}
965
 
964
 
966
 
965
 
967
/****************************************************************************************************************************************/
966
/****************************************************************************************************************************************/
968
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
967
/* Function:    u16 AppendCluster(File *file);                                                                                                                                                                                  */
969
/*                                                                                                                                                                                                                                                                              */
968
/*                                                                                                                                                                                                                                                                              */
970
/* 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.                                                                */
971
/*                                                                                                                                                                                                                                                                              */
970
/*                                                                                                                                                                                                                                                                              */
972
/* 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.                                                */
973
/****************************************************************************************************************************************/
972
/****************************************************************************************************************************************/
974
u16 AppendCluster(File_t *file)
973
u16 AppendCluster(File_t *file)
975
{
974
{
976
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
975
        u16 last_cluster, new_cluster = CLUSTER_UNDEFINED;
977
        u32 fat_byte_offset, sector, byte;
976
        u32 fat_byte_offset, sector, byte;
978
        Fat16Entry_t * fat;
977
        Fat16Entry_t * fat;
979
 
978
 
980
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
979
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
981
 
980
 
982
        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.
983
        if(new_cluster != CLUSTER_UNDEFINED)
982
        if(new_cluster != CLUSTER_UNDEFINED)
984
        {       // 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.
985
                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
986
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
985
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
987
                if(last_cluster != CLUSTER_UNDEFINED)
986
                if(last_cluster != CLUSTER_UNDEFINED)
988
                {
987
                {
989
                        // update FAT entry of last cluster
988
                        // update FAT entry of last cluster
990
                        fat_byte_offset = ((u32)last_cluster)<<1;
989
                        fat_byte_offset = ((u32)last_cluster)<<1;
991
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
990
                        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
992
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
991
                        byte = fat_byte_offset % BYTES_PER_SECTOR;
993
                        // read the sector containing the last cluster of the file
992
                        // read the sector containing the last cluster of the file
994
                        if(file->SectorInCache != sector)
993
                        if(file->SectorInCache != sector)
995
                        {
994
                        {
996
                                file->SectorInCache = sector;   // update sector stored in buffer
995
                                file->SectorInCache = sector;   // update sector stored in buffer
997
                                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
998
                                {
997
                                {
999
                                        Fat16_Deinit();
998
                                        Fat16_Deinit();
1000
                                        return(0);
999
                                        return(0);
1001
                                }
1000
                                }
1002
                        }
1001
                        }
1003
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
1002
                        fat = (Fat16Entry_t *)(&(file->Cache[byte]));
1004
                        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.
1005
                        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.
1006
                        {
1005
                        {
1007
                                Fat16_Deinit();
1006
                                Fat16_Deinit();
1008
                                return(0);
1007
                                return(0);
1009
                        }
1008
                        }
1010
                }
1009
                }
1011
                else // last cluster of the file is undefined
1010
                else // last cluster of the file is undefined
1012
                {   // 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
1013
                    // and its cluster number must be set in the direntry
1012
                    // and its cluster number must be set in the direntry
1014
                        DirEntry_t * dir;
1013
                        DirEntry_t * dir;
1015
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1014
                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1016
                        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.
1017
                        {
1016
                        {
1018
                                Fat16_Deinit();
1017
                                Fat16_Deinit();
1019
                                return(CLUSTER_UNDEFINED);
1018
                                return(CLUSTER_UNDEFINED);
1020
                        }
1019
                        }
1021
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1020
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1022
                        dir[file->DirectoryIndex].Res1 = 0;
1021
                        dir[file->DirectoryIndex].Res1 = 0;
1023
                        dir[file->DirectoryIndex].Res2[0] = 0;
1022
                        dir[file->DirectoryIndex].Res2[0] = 0;
1024
                        dir[file->DirectoryIndex].Res2[1] = 0;
1023
                        dir[file->DirectoryIndex].Res2[1] = 0;
1025
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster 
1024
                        dir[file->DirectoryIndex].StartCluster = new_cluster;           // update startcluster 
1026
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
1025
                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);// set time
1027
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1026
                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);// and date of modification
1028
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1027
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1029
                        dir[file->DirectoryIndex].Size          = 0;
1028
                        dir[file->DirectoryIndex].Size          = 0;
1030
                        // write sector containing the direntry
1029
                        // write sector containing the direntry
1031
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1030
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1032
                        {
1031
                        {
1033
                                Fat16_Deinit();
1032
                                Fat16_Deinit();
1034
                                return(CLUSTER_UNDEFINED);
1033
                                return(CLUSTER_UNDEFINED);
1035
                        }
1034
                        }
1036
                        // update file info     
1035
                        // update file info     
1037
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1036
                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster);
1038
                        file->Size = 0;
1037
                        file->Size = 0;
1039
                        file->Position = 0;
1038
                        file->Position = 0;
1040
                }
1039
                }
1041
                // update file pointes
1040
                // update file pointes
1042
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1041
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
1043
                file->SectorOfCurrCluster = 0;
1042
                file->SectorOfCurrCluster = 0;
1044
                file->ByteOfCurrSector = 0;
1043
                file->ByteOfCurrSector = 0;
1045
        }
1044
        }
1046
        return(new_cluster);
1045
        return(new_cluster);
1047
}
1046
}
1048
 
1047
 
1049
/****************************************************************************************************************************************************/
1048
/****************************************************************************************************************************************************/
1050
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1049
/* Function:    DirectoryEntryExist(s8 *, u8, u8, File_t *)                                                                                                                                                                                     */
1051
/*                                                                                                                                                                                                                                                                                                      */
1050
/*                                                                                                                                                                                                                                                                                                      */
1052
/* 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                     */
1053
/*                                                                                                                                                                                                                                                                                                      */
1052
/*                                                                                                                                                                                                                                                                                                      */
1054
/* 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.                                                                                                                                     */
1055
/****************************************************************************************************************************************************/
1054
/****************************************************************************************************************************************************/
1056
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1055
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
1057
{
1056
{
1058
        u32             dir_sector, max_dir_sector, curr_sector;
1057
        u32             dir_sector, max_dir_sector, curr_sector;
1059
        u16     dir_entry = 0;
1058
        u16     dir_entry = 0;
1060
 
1059
 
1061
        u16     end_of_directory_not_reached = 0;
1060
        u16     end_of_directory_not_reached = 0;
1062
        u8              i = 0;
1061
        u8              i = 0;
1063
        u8      direntry_exist = 0;
1062
        u8      direntry_exist = 0;
1064
        DirEntry_t * dir;
1063
        DirEntry_t * dir;
1065
 
1064
 
1066
        // if incomming pointers are useless return immediatly
1065
        // if incomming pointers are useless return immediatly
1067
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1066
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
1068
 
1067
 
1069
        // dir entries can be searched only in filesclusters that have
1068
        // dir entries can be searched only in filesclusters that have
1070
        // a corresponding dir entry with adir-flag set in its attribute
1069
        // a corresponding dir entry with adir-flag set in its attribute
1071
        // or direct within the root directory area
1070
        // or direct within the root directory area
1072
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1071
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1073
        // no current directory exist therefore assume searching in the root
1072
        // no current directory exist therefore assume searching in the root
1074
        if(file->DirectorySector == SECTOR_UNDEFINED)
1073
        if(file->DirectorySector == SECTOR_UNDEFINED)
1075
        {
1074
        {
1076
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1075
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1077
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1076
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1078
        }
1077
        }
1079
        // 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
1080
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1079
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1081
        {
1080
        {
1082
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1081
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1083
        }
1082
        }
1084
        // 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
1085
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1084
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1086
        {
1085
        {
1087
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
1086
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
1088
        }
1087
        }
1089
        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
1090
        // if search area is not defined yet
1089
        // if search area is not defined yet
1091
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1090
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1092
        {
1091
        {
1093
                // 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
1094
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1093
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1095
                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.
1096
                {
1095
                {
1097
                        Fat16_Deinit();
1096
                        Fat16_Deinit();
1098
                        return(direntry_exist);
1097
                        return(direntry_exist);
1099
                }
1098
                }
1100
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1099
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1101
                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
1102
                {
1101
                {
1103
                        case SLOT_EMPTY:
1102
                        case SLOT_EMPTY:
1104
                        case SLOT_DELETED:
1103
                        case SLOT_DELETED:
1105
                                // 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
1106
                                // therefore no file or subdirectory can be created
1105
                                // therefore no file or subdirectory can be created
1107
                                return (direntry_exist);
1106
                                return (direntry_exist);
1108
                                break;
1107
                                break;
1109
                        default:        // and is a real directory
1108
                        default:        // and is a real directory
1110
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1109
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1111
                                {       // 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
1112
                                        return (direntry_exist);
1111
                                        return (direntry_exist);
1113
                                }
1112
                                }
1114
                                break;
1113
                                break;
1115
                }
1114
                }
1116
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
1115
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
1117
        }
1116
        }
1118
 
1117
 
1119
        // update current file data area position to start of first cluster
1118
        // update current file data area position to start of first cluster
1120
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1119
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1121
        file->SectorOfCurrCluster               = 0;
1120
        file->SectorOfCurrCluster               = 0;
1122
        file->ByteOfCurrSector                  = 0;
1121
        file->ByteOfCurrSector                  = 0;
1123
 
1122
 
1124
        do // loop over all data clusters of the current directory entry
1123
        do // loop over all data clusters of the current directory entry
1125
        {
1124
        {
1126
                dir_sector = 0;
1125
                dir_sector = 0;
1127
                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
1128
                {
1127
                {
1129
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1128
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1130
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1129
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1131
                        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
1132
                        {
1131
                        {
1133
                                Fat16_Deinit();
1132
                                Fat16_Deinit();
1134
                                return(direntry_exist);
1133
                                return(direntry_exist);
1135
                        }
1134
                        }
1136
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1135
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1137
                        // search all directory entries within that sector
1136
                        // search all directory entries within that sector
1138
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1137
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1139
                        {   // check for existing dir entry
1138
                        {   // check for existing dir entry
1140
                                switch((u8)dir[dir_entry].Name[0])
1139
                                switch((u8)dir[dir_entry].Name[0])
1141
                                {
1140
                                {
1142
                                        case SLOT_EMPTY:
1141
                                        case SLOT_EMPTY:
1143
                                        case SLOT_DELETED:
1142
                                        case SLOT_DELETED:
1144
                                                // ignore empty or deleted dir entries
1143
                                                // ignore empty or deleted dir entries
1145
                                                break;
1144
                                                break;
1146
                                        default:
1145
                                        default:
1147
                                                // if existing check attributes before names are compared will safe performance
1146
                                                // if existing check attributes before names are compared will safe performance
1148
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1147
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
1149
                                                // 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.)
1150
                                                i = 0;
1149
                                                i = 0;
1151
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1150
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
1152
                                                if (i < 10) break; // names does not match
1151
                                                if (i < 10) break; // names does not match
1153
                                                // if dirname and attribute have matched
1152
                                                // if dirname and attribute have matched
1154
                                                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
1155
                                                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
1156
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1155
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1157
                                                file->SectorOfCurrCluster = 0;
1156
                                                file->SectorOfCurrCluster = 0;
1158
                                                file->ByteOfCurrSector = 0;
1157
                                                file->ByteOfCurrSector = 0;
1159
                                                file->DirectorySector = curr_sector; // current sector
1158
                                                file->DirectorySector = curr_sector; // current sector
1160
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1159
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
1161
                                                file->Size = dir[dir_entry].Size;
1160
                                                file->Size = dir[dir_entry].Size;
1162
                                                direntry_exist = 1; // mark as found
1161
                                                direntry_exist = 1; // mark as found
1163
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1162
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1164
                                } // end of first byte of name check
1163
                                } // end of first byte of name check
1165
                        }
1164
                        }
1166
                        dir_sector++; // search next sector
1165
                        dir_sector++; // search next sector
1167
                // 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
1168
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1167
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
1169
 
1168
 
1170
                // 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.
1171
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1170
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1172
                {
1171
                {
1173
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1172
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1174
                }
1173
                }
1175
        }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
1176
        return(direntry_exist);
1175
        return(direntry_exist);
1177
}
1176
}
1178
 
1177
 
1179
 
1178
 
1180
/****************************************************************************************************************************************/
1179
/****************************************************************************************************************************************/
1181
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1180
/*      Function:               CreateDirectoryEntry(s8 *, u16, File_t *)                                                                                                                                                       */
1182
/*                                                                                                                                                                                                                                                                              */
1181
/*                                                                                                                                                                                                                                                                              */
1183
/*      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.                                                           */
1184
/*                                      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.                                                                                                      */
1185
/*                                                                                                                                                                                                                                                                              */
1184
/*                                                                                                                                                                                                                                                                              */
1186
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1185
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
1187
/****************************************************************************************************************************************/
1186
/****************************************************************************************************************************************/
1188
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1187
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
1189
{
1188
{
1190
        u32 dir_sector, max_dir_sector, curr_sector;
1189
        u32 dir_sector, max_dir_sector, curr_sector;
1191
        u16 dir_entry   = 0;
1190
        u16 dir_entry   = 0;
1192
        u16 subdircluster, dircluster = 0;
1191
        u16 subdircluster, dircluster = 0;
1193
        u16 end_of_directory_not_reached = 0;
1192
        u16 end_of_directory_not_reached = 0;
1194
        u8      i                       = 0;
1193
        u8      i                       = 0;
1195
        u8      retvalue        = 0;
1194
        u8      retvalue        = 0;
1196
        DirEntry_t *dir;
1195
        DirEntry_t *dir;
1197
 
1196
 
1198
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
1197
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
1199
        // 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!
1200
 
1199
 
1201
        // Dir entries can be created only in file-clusters that have
1200
        // Dir entries can be created only in file-clusters that have
1202
        // 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
1203
 
1202
 
1204
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1203
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1205
        // no current directory exist therefore assume creating in the root
1204
        // no current directory exist therefore assume creating in the root
1206
        if(file->DirectorySector == SECTOR_UNDEFINED)
1205
        if(file->DirectorySector == SECTOR_UNDEFINED)
1207
        {
1206
        {
1208
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1207
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1209
                dircluster = 0;
1208
                dircluster = 0;
1210
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1209
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
1211
        }
1210
        }
1212
        // 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
1213
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1212
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
1214
        {
1213
        {
1215
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1214
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1216
        }
1215
        }
1217
        // 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
1218
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1217
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1219
        {
1218
        {
1220
                max_dir_sector = Partition.SectorsPerCluster;
1219
                max_dir_sector = Partition.SectorsPerCluster;
1221
        }
1220
        }
1222
        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
1223
        // if search area is not defined yet
1222
        // if search area is not defined yet
1224
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1223
        if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)
1225
        {
1224
        {
1226
            // 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
1227
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1226
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1228
                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.
1229
                {
1228
                {
1230
                        Fat16_Deinit();
1229
                        Fat16_Deinit();
1231
                        return(retvalue);
1230
                        return(retvalue);
1232
                }
1231
                }
1233
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1232
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1234
                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
1235
                {
1234
                {
1236
                        case SLOT_EMPTY:
1235
                        case SLOT_EMPTY:
1237
                        case SLOT_DELETED:
1236
                        case SLOT_DELETED:
1238
                                return (retvalue);
1237
                                return (retvalue);
1239
                                break;
1238
                                break;
1240
                        default:        // and is a real directory
1239
                        default:        // and is a real directory
1241
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1240
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1242
                                {       // 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
1243
                                        return (retvalue);
1242
                                        return (retvalue);
1244
                                }
1243
                                }
1245
                                break;
1244
                                break;
1246
                }
1245
                }
1247
                dircluster = dir[file->DirectoryIndex].StartCluster;
1246
                dircluster = dir[file->DirectoryIndex].StartCluster;
1248
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1247
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1249
        }
1248
        }
1250
 
1249
 
1251
        // if the new direntry is a subdirectory
1250
        // if the new direntry is a subdirectory
1252
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1251
        if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)
1253
        {       // get a free clutser for its content
1252
        {       // get a free clutser for its content
1254
                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.
1255
        }
1254
        }
1256
        else // a normal file
1255
        else // a normal file
1257
        {       // has no data cluster after creation
1256
        {       // has no data cluster after creation
1258
                subdircluster = CLUSTER_UNDEFINED;
1257
                subdircluster = CLUSTER_UNDEFINED;
1259
        }
1258
        }
1260
 
1259
 
1261
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1260
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1262
        file->SectorOfCurrCluster               = 0;
1261
        file->SectorOfCurrCluster               = 0;
1263
        do // loop over all clusters of current directory
1262
        do // loop over all clusters of current directory
1264
        {
1263
        {
1265
                dir_sector = 0; // reset sector counter within a new cluster
1264
                dir_sector = 0; // reset sector counter within a new cluster
1266
                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
1267
                {
1266
                {
1268
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1267
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1269
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1268
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1270
                        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.
1271
                        {
1270
                        {
1272
                                Fat16_Deinit();
1271
                                Fat16_Deinit();
1273
                                return(retvalue);
1272
                                return(retvalue);
1274
                        }
1273
                        }
1275
 
1274
 
1276
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1275
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1277
                        // search all directory entries of a sector
1276
                        // search all directory entries of a sector
1278
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1277
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1279
                        {       // check if current direntry is available
1278
                        {       // check if current direntry is available
1280
                                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))
1281
                                {       // a free direntry was found
1280
                                {       // a free direntry was found
1282
                                        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
1283
                                        dir[dir_entry].Attribute    = attrib;
1282
                                        dir[dir_entry].Attribute    = attrib;
1284
                                        dir[dir_entry].Res1 = 0;
1283
                                        dir[dir_entry].Res1 = 0;
1285
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1284
                                        dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10);
1286
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1285
                                        dir[dir_entry].CreationTime     = FileTime(&SystemTime);
1287
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1286
                                        dir[dir_entry].CreationDate     = FileDate(&SystemTime);
1288
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1287
                                        dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate;
1289
                                        dir[dir_entry].Res2[0] = 0;
1288
                                        dir[dir_entry].Res2[0] = 0;
1290
                                        dir[dir_entry].Res2[1] = 0;
1289
                                        dir[dir_entry].Res2[1] = 0;
1291
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1290
                                        dir[dir_entry].ModTime = dir[dir_entry].CreationTime;
1292
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1291
                                        dir[dir_entry].ModDate = dir[dir_entry].CreationDate;
1293
                                        // Set the attribute of the new directoryentry.
1292
                                        // Set the attribute of the new directoryentry.
1294
                                        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.
1295
                                        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.
1296
                                        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
1297
                                        {
1296
                                        {
1298
                                                Fat16_Deinit();
1297
                                                Fat16_Deinit();
1299
                                                return(retvalue);
1298
                                                return(retvalue);
1300
                                        }
1299
                                        }
1301
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1300
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1302
                                        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.
1303
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1302
                                        file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1304
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1303
                                        file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1305
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1304
                                        file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1306
                                        file->Size                                              = 0;                                                        // new file has no size
1305
                                        file->Size                                              = 0;                                                        // new file has no size
1307
                                        file->DirectorySector                   = curr_sector;
1306
                                        file->DirectorySector                   = curr_sector;
1308
                                        file->DirectoryIndex                    = dir_entry;
1307
                                        file->DirectoryIndex                    = dir_entry;
1309
                                        // prepare subdirectory data cluster
1308
                                        // prepare subdirectory data cluster
1310
                                        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
1311
                                        {
1310
                                        {
1312
                                                ClearCurrCluster(file); // fill cluster with zeros
1311
                                                ClearCurrCluster(file); // fill cluster with zeros
1313
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1312
                                                file->SectorInCache = file->FirstSectorOfFirstCluster;
1314
                                                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.
1315
                                                {
1314
                                                {
1316
                                                        Fat16_Deinit();
1315
                                                        Fat16_Deinit();
1317
                                                        return(retvalue);
1316
                                                        return(retvalue);
1318
                                                }
1317
                                                }
1319
                                                dir = (DirEntry_t *)file->Cache;
1318
                                                dir = (DirEntry_t *)file->Cache;
1320
                                                // create direntry "." to current dir
1319
                                                // create direntry "." to current dir
1321
                                                dir[0].Name[0] = 0x2E;
1320
                                                dir[0].Name[0] = 0x2E;
1322
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1321
                                                for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1323
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1322
                                                dir[0].Attribute = ATTR_SUBDIRECTORY;
1324
                                                dir[0].StartCluster = subdircluster;
1323
                                                dir[0].StartCluster = subdircluster;
1325
                                                dir[0].Size = 0;
1324
                                                dir[0].Size = 0;
1326
                                                // create direntry ".." to the upper dir
1325
                                                // create direntry ".." to the upper dir
1327
                                                dir[1].Name[0] = 0x2E;
1326
                                                dir[1].Name[0] = 0x2E;
1328
                                                dir[1].Name[1] = 0x2E;
1327
                                                dir[1].Name[1] = 0x2E;
1329
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1328
                                                for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1330
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1329
                                                dir[1].Attribute = ATTR_SUBDIRECTORY;
1331
                                                dir[1].StartCluster = dircluster;
1330
                                                dir[1].StartCluster = dircluster;
1332
                                                dir[1].Size = 0;
1331
                                                dir[1].Size = 0;
1333
                                                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.
1334
                                                {
1333
                                                {
1335
                                                        Fat16_Deinit();
1334
                                                        Fat16_Deinit();
1336
                                                        return(retvalue);
1335
                                                        return(retvalue);
1337
                                                }
1336
                                                }
1338
                                        }
1337
                                        }
1339
                                        retvalue = 1;
1338
                                        retvalue = 1;
1340
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1339
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1341
                                }
1340
                                }
1342
                        }
1341
                        }
1343
                        dir_sector++; // search next sector
1342
                        dir_sector++; // search next sector
1344
                // 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
1345
                }while((dir_sector < max_dir_sector) && (!retvalue));
1344
                }while((dir_sector < max_dir_sector) && (!retvalue));
1346
 
1345
 
1347
                // 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.
1348
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1347
                if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1349
                {
1348
                {
1350
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1349
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1351
                }
1350
                }
1352
        }while((end_of_directory_not_reached) && (!retvalue));
1351
        }while((end_of_directory_not_reached) && (!retvalue));
1353
        // 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.
1354
        // 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.
1355
        // 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
1356
        // within a subdirectory of root.
1355
        // within a subdirectory of root.
1357
 
1356
 
1358
        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.
1359
}
1358
}
1360
 
1359
 
1361
/********************************************************************************************************************************************/
1360
/********************************************************************************************************************************************/
1362
/*      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);                                                                                    */
1363
/*                                                                                                                                                                                                                                                                                      */
1362
/*                                                                                                                                                                                                                                                                                      */
1364
/*      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                                                                               */
1365
/*                                      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                                                                  */
1366
/*                                      updated.                                                                                                                                                                                                                                */
1365
/*                                      updated.                                                                                                                                                                                                                                */
1367
/*                                                                                                                                                                                                                                                                                      */
1366
/*                                                                                                                                                                                                                                                                                      */
1368
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1367
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1369
/********************************************************************************************************************************************/
1368
/********************************************************************************************************************************************/
1370
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)
1371
{
1370
{
1372
        s8* path = 0;
1371
        s8* path = 0;
1373
        s8* subpath = 0;
1372
        s8* subpath = 0;
1374
        u8 af, am, file_exist = 0;
1373
        u8 af, am, file_exist = 0;
1375
        s8 dirname[12]; // 8+3 + temination character
1374
        s8 dirname[12]; // 8+3 + temination character
1376
 
1375
 
1377
        // if incomming pointers are useless return immediatly
1376
        // if incomming pointers are useless return immediatly
1378
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1377
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1379
 
1378
 
1380
        // trace along the filepath
1379
        // trace along the filepath
1381
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1380
        path = (s8*)filename;                                                           // start a the beginning of the filename string
1382
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1381
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1383
        file->DirectoryIndex = 0;
1382
        file->DirectoryIndex = 0;
1384
        /* 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 */
1385
        if(path[0] != '/')
1384
        if(path[0] != '/')
1386
        {
1385
        {
1387
                /* is the current working directory the rootdirectory? */
1386
                /* is the current working directory the rootdirectory? */
1388
                if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0;
1387
                if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0;
1389
                /* otherwise we are working in an subdirectory */
1388
                /* otherwise we are working in an subdirectory */
1390
                else file->DirectorySector = Partition.CurrentWorkingDirectory;
1389
                else file->DirectorySector = Partition.CurrentWorkingDirectory;
1391
        }
1390
        }
1392
        // 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
1393
        while((*path != 0) && !file_exist)
1392
        while((*path != 0) && !file_exist)
1394
        {       // separate dirname and subpath from filepath string
1393
        {       // separate dirname and subpath from filepath string
1395
                subpath = SeperateDirName(path, dirname);
1394
                subpath = SeperateDirName(path, dirname);
1396
                if(subpath != NULL)
1395
                if(subpath != NULL)
1397
                {
1396
                {
1398
                        if(*subpath == 0)
1397
                        if(*subpath == 0)
1399
                        {       // empty subpath indicates last element of dir chain
1398
                        {       // empty subpath indicates last element of dir chain
1400
                                af = attribfilter;
1399
                                af = attribfilter;
1401
                                am = attribmask;
1400
                                am = attribmask;
1402
                        }
1401
                        }
1403
                        else  // it must be a subdirectory and no volume label
1402
                        else  // it must be a subdirectory and no volume label
1404
                        {
1403
                        {
1405
                                af = ATTR_SUBDIRECTORY;
1404
                                af = ATTR_SUBDIRECTORY;
1406
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1405
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1407
                        }
1406
                        }
1408
                        if(!DirectoryEntryExist(dirname, af, am, file))
1407
                        if(!DirectoryEntryExist(dirname, af, am, file))
1409
                        {
1408
                        {
1410
                                return (file_exist); // subdirectory does not exist
1409
                                return (file_exist); // subdirectory does not exist
1411
                        }
1410
                        }
1412
                        else
1411
                        else
1413
                        {
1412
                        {
1414
                                if (*subpath == 0)
1413
                                if (*subpath == 0)
1415
                                {
1414
                                {
1416
                                        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
1417
                                }
1416
                                }
1418
                        }
1417
                        }
1419
                }
1418
                }
1420
                else // error seperating the subpath
1419
                else // error seperating the subpath
1421
                {
1420
                {
1422
                        return file_exist; // bad subdir format
1421
                        return file_exist; // bad subdir format
1423
                }
1422
                }
1424
                path = subpath;
1423
                path = subpath;
1425
                subpath = 0;
1424
                subpath = 0;
1426
        }
1425
        }
1427
        return (file_exist);
1426
        return (file_exist);
1428
}
1427
}
1429
 
1428
 
1430
 
1429
 
1431
/********************************************************************************************************************************************/
1430
/********************************************************************************************************************************************/
1432
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1431
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1433
/*                                                                                                                                                                                                                                                                                      */
1432
/*                                                                                                                                                                                                                                                                                      */
1434
/*      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                                                                               */
1435
/*                                      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                                                              */
1436
/*                                      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                                                                                               */
1437
/*                                                                                                                                                                                                                                                                                      */
1436
/*                                                                                                                                                                                                                                                                                      */
1438
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1437
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1439
/********************************************************************************************************************************************/
1438
/********************************************************************************************************************************************/
1440
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1439
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
1441
{
1440
{
1442
        s8 *path = 0;
1441
        s8 *path = 0;
1443
        s8 *subpath = 0;
1442
        s8 *subpath = 0;
1444
        u8 af, am, file_created = 0;
1443
        u8 af, am, file_created = 0;
1445
        s8 dirname[12];
1444
        s8 dirname[12];
1446
 
1445
 
1447
        // if incomming pointers are useless return immediatly
1446
        // if incomming pointers are useless return immediatly
1448
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1447
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1449
 
1448
 
1450
        // trace along the filepath
1449
        // trace along the filepath
1451
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
1450
        path = (s8*)filename;                                                                   // start a the beginning of the filename string
1452
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1451
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1453
        file->DirectoryIndex = 0;
1452
        file->DirectoryIndex = 0;
1454
        // 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
1455
        while((*path != 0) && !file_created)
1454
        while((*path != 0) && !file_created)
1456
        {   // separate dirname and subpath from filepath string
1455
        {   // separate dirname and subpath from filepath string
1457
                subpath = SeperateDirName(path, dirname);
1456
                subpath = SeperateDirName(path, dirname);
1458
                if(subpath != NULL)
1457
                if(subpath != NULL)
1459
                {
1458
                {
1460
                        if(*subpath == 0)
1459
                        if(*subpath == 0)
1461
                        {       // empty subpath indicates last element of dir chain
1460
                        {       // empty subpath indicates last element of dir chain
1462
                                af = ATTR_NONE;
1461
                                af = ATTR_NONE;
1463
                                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
1464
                        }
1463
                        }
1465
                        else  // it must be a subdirectory and no volume label
1464
                        else  // it must be a subdirectory and no volume label
1466
                        {
1465
                        {
1467
                                af = ATTR_SUBDIRECTORY;
1466
                                af = ATTR_SUBDIRECTORY;
1468
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1467
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1469
                        }
1468
                        }
1470
                        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
1471
                        {  // try to create subdir or file
1470
                        {  // try to create subdir or file
1472
                                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
1473
                                if(!CreateDirectoryEntry(dirname, af, file))
1472
                                if(!CreateDirectoryEntry(dirname, af, file))
1474
                                {       // could not be created
1473
                                {       // could not be created
1475
                                        return(file_created);
1474
                                        return(file_created);
1476
                                }
1475
                                }
1477
                                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
1478
                        }
1477
                        }
1479
                }
1478
                }
1480
                else // error seperating the subpath
1479
                else // error seperating the subpath
1481
                {
1480
                {
1482
                        return file_created; // bad subdir format
1481
                        return file_created; // bad subdir format
1483
                }
1482
                }
1484
                path = subpath;
1483
                path = subpath;
1485
                subpath = 0;
1484
                subpath = 0;
1486
        }
1485
        }
1487
        return (file_created);
1486
        return (file_created);
1488
}
1487
}
1489
 
1488
 
1490
 
1489
 
1491
/********************************************************************************************************************************************/
1490
/********************************************************************************************************************************************/
1492
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1491
/*      Function:               File_t * fopen_(s8* filename, s8 mode);                                                                                                                                                                 */
1493
/*                                                                                                                                                                                                                                                                                      */
1492
/*                                                                                                                                                                                                                                                                                      */
1494
/*      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    */
1495
/*                                      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.                                             */
1496
/*                                                                                                                                                                                                                                                                                      */
1495
/*                                                                                                                                                                                                                                                                                      */
1497
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1496
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1498
/********************************************************************************************************************************************/
1497
/********************************************************************************************************************************************/
1499
File_t * fopen_(s8 * const filename, const s8 mode)
1498
File_t * fopen_(s8 * const filename, const s8 mode)
1500
{
1499
{
1501
        File_t *file    = 0;
1500
        File_t *file    = 0;
1502
        s8 *cptr;
1501
        s8 *cptr;
1503
 
1502
 
1504
        if((!Partition.IsValid) || (filename == 0)) return(file);
1503
        if((!Partition.IsValid) || (filename == 0)) return(file);
1505
 
1504
 
1506
        // Look for an unused filepointer in the file pointer list?
1505
        // Look for an unused filepointer in the file pointer list?
1507
        file = LockFilePointer();
1506
        file = LockFilePointer();
1508
        // if no unused file pointer was found return 0
1507
        // if no unused file pointer was found return 0
1509
        if(file == NULL) return(file);
1508
        if(file == NULL) return(file);
1510
 
1509
 
1511
        // now we have found a free filepointer and claimed it
1510
        // now we have found a free filepointer and claimed it
1512
        // so let initiate its property values
1511
        // so let initiate its property values
1513
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;             // Sectorpointer to the first sector of the first datacluster of the file.
1512
        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;             // Sectorpointer to the first sector of the first datacluster of the file.
1514
        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;             // Pointer to the cluster which is edited at the moment.
1513
        file->FirstSectorOfCurrCluster  = SECTOR_UNDEFINED;             // Pointer to the cluster which is edited at the moment.
1515
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1514
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1516
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1515
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1517
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1516
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1518
        file->Size                                              = 0;            // the size of the opened file in bytes.
1517
        file->Size                                              = 0;            // the size of the opened file in bytes.
1519
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1518
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1520
        file->SectorInCache                             = SECTOR_UNDEFINED;             // the last sector read, wich is still in the sectorbuffer.
1519
        file->SectorInCache                             = SECTOR_UNDEFINED;             // the last sector read, wich is still in the sectorbuffer.
1521
        file->DirectorySector                   = SECTOR_UNDEFINED;             // the sectorposition where the directoryentry has been made.
1520
        file->DirectorySector                   = SECTOR_UNDEFINED;             // the sectorposition where the directoryentry has been made.
1522
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1521
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1523
        file->Attribute                                 = 0;            // the attribute of the file opened.
1522
        file->Attribute                                 = 0;            // the attribute of the file opened.
1524
 
1523
 
1525
        // bring the path into the correct syntax 
1524
        // bring the path into the correct syntax 
1526
        cptr = filename;
1525
        cptr = filename;
1527
        // search the whole string 
1526
        // search the whole string 
1528
        while(*cptr != 0)
1527
        while(*cptr != 0)
1529
        {
1528
        {
1530
                // replace all '\' by '/'
1529
                // replace all '\' by '/'
1531
                if(*cptr == '\\') *cptr = '/';
1530
                if(*cptr == '\\') *cptr = '/';
1532
                cptr++;
1531
                cptr++;
1533
        }
1532
        }
1534
        // check if a real file (no directory) to the given filename exist
1533
        // check if a real file (no directory) to the given filename exist
1535
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1534
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1536
        {  // file exist
1535
        {  // file exist
1537
                switch(mode)  // check mode
1536
                switch(mode)  // check mode
1538
                {
1537
                {
1539
                        case 'a':       // if mode is: append to file
1538
                        case 'a':       // if mode is: append to file
1540
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1539
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1541
                                {       // file is marked as readonly --> do not open this file
1540
                                {       // file is marked as readonly --> do not open this file
1542
                                        fclose_(file);
1541
                                        fclose_(file);
1543
                                        file = NULL;
1542
                                        file = NULL;
1544
                                }
1543
                                }
1545
                                else
1544
                                else
1546
                                {       // file is not marked as read only --> goto end of file
1545
                                {       // file is not marked as read only --> goto end of file
1547
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1546
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1548
                                }
1547
                                }
1549
                                break;
1548
                                break;
1550
                        case 'w':       // if mode is: write to file
1549
                        case 'w':       // if mode is: write to file
1551
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1550
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1552
                                {       // file is marked as readonly --> do not open this file
1551
                                {       // file is marked as readonly --> do not open this file
1553
                                        fclose_(file);
1552
                                        fclose_(file);
1554
                                        file = NULL;
1553
                                        file = NULL;
1555
                                }
1554
                                }
1556
                                else
1555
                                else
1557
                                {       // file is not marked as read only
1556
                                {       // file is not marked as read only
1558
                                        DirEntry_t * dir;
1557
                                        DirEntry_t * dir;
1559
                                        // free all clusters of that file
1558
                                        // free all clusters of that file
1560
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1559
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1561
                                        // update directory entry of that file
1560
                                        // update directory entry of that file
1562
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1561
                                        file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1563
                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1562
                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1564
                                        {
1563
                                        {
1565
                                                Fat16_Deinit();
1564
                                                Fat16_Deinit();
1566
                                                return(NULL);
1565
                                                return(NULL);
1567
                                        }
1566
                                        }
1568
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1567
                                        dir = (DirEntry_t *)file->Cache;                                                                // set pointer to directory
1569
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1568
                                    dir[file->DirectoryIndex].ModTime   = FileTime(&SystemTime);        // set modification time
1570
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1569
                                        dir[file->DirectoryIndex].ModDate       = FileDate(&SystemTime);        // set modification date
1571
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1570
                                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1572
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster 
1571
                                        dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED;             // update startcluster 
1573
                                        dir[file->DirectoryIndex].Size          = 0;
1572
                                        dir[file->DirectoryIndex].Size          = 0;
1574
                                        // write sector containing the direntry
1573
                                        // write sector containing the direntry
1575
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1574
                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1576
                                        {
1575
                                        {
1577
                                                Fat16_Deinit();
1576
                                                Fat16_Deinit();
1578
                                                return(NULL);
1577
                                                return(NULL);
1579
                                        }
1578
                                        }
1580
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1579
                                        file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
1581
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1580
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1582
                                        file->SectorOfCurrCluster = 0;
1581
                                        file->SectorOfCurrCluster = 0;
1583
                                        file->ByteOfCurrSector = 0;
1582
                                        file->ByteOfCurrSector = 0;
1584
                                        file->Size = 0;
1583
                                        file->Size = 0;
1585
                                        file->Position = 0;
1584
                                        file->Position = 0;
1586
                                        fseek_(file, 0, SEEK_SET);
1585
                                        fseek_(file, 0, SEEK_SET);
1587
                                }
1586
                                }
1588
                                break;
1587
                                break;
1589
                        case 'r':       // if mode is: read from file
1588
                        case 'r':       // if mode is: read from file
1590
                                // goto end of file
1589
                                // goto end of file
1591
                                fseek_(file, 0, SEEK_SET);
1590
                                fseek_(file, 0, SEEK_SET);
1592
                                break;
1591
                                break;
1593
                        default: // other modes are not supported
1592
                        default: // other modes are not supported
1594
                                fclose_(file);
1593
                                fclose_(file);
1595
                                file = NULL;
1594
                                file = NULL;
1596
                        break;
1595
                        break;
1597
                }
1596
                }
1598
                return(file);
1597
                return(file);
1599
        }
1598
        }
1600
        else // file does not exist
1599
        else // file does not exist
1601
        {
1600
        {
1602
                switch(mode)  // check mode
1601
                switch(mode)  // check mode
1603
                {
1602
                {
1604
                        case 'a':
1603
                        case 'a':
1605
                        case 'w': // if mode is write or append
1604
                        case 'w': // if mode is write or append
1606
                                // try to create the file
1605
                                // try to create the file
1607
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1606
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1608
                                { // if it could not be created
1607
                                { // if it could not be created
1609
                                        fclose_(file);
1608
                                        fclose_(file);
1610
                                        file = NULL;
1609
                                        file = NULL;
1611
                                }
1610
                                }
1612
                                break;
1611
                                break;
1613
                        case 'r': // else opened for 'r'
1612
                        case 'r': // else opened for 'r'
1614
                        default:  // if unsupported mode
1613
                        default:  // if unsupported mode
1615
                                fclose_(file);
1614
                                fclose_(file);
1616
                                file = NULL;
1615
                                file = NULL;
1617
                                break;
1616
                                break;
1618
                }
1617
                }
1619
                return(file);
1618
                return(file);
1620
        }
1619
        }
1621
        // we should never come to this point
1620
        // we should never come to this point
1622
        fclose_(file);
1621
        fclose_(file);
1623
        file = NULL;
1622
        file = NULL;
1624
        return(file);
1623
        return(file);
1625
}
1624
}
1626
 
1625
 
1627
/****************************************************************************************************************************************************/
1626
/****************************************************************************************************************************************************/
1628
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1627
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1629
/*                                                                                                                                                                                                                                                                                                      */
1628
/*                                                                                                                                                                                                                                                                                                      */
1630
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1629
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1631
/*                                                                                                                                                                                                                                                                                                      */
1630
/*                                                                                                                                                                                                                                                                                                      */
1632
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1631
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1633
/****************************************************************************************************************************************************/
1632
/****************************************************************************************************************************************************/
1634
s16     fflush_(File_t *file)
1633
s16     fflush_(File_t *file)
1635
{
1634
{
1636
        DirEntry_t *dir;
1635
        DirEntry_t *dir;
1637
 
1636
 
1638
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1637
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1639
 
1638
 
1640
        switch(file->Mode)
1639
        switch(file->Mode)
1641
        {
1640
        {
1642
                case 'a':
1641
                case 'a':
1643
                case 'w':
1642
                case 'w':
1644
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1643
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1645
                        {
1644
                        {
1646
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1645
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1647
                                {
1646
                                {
1648
                                        Fat16_Deinit();
1647
                                        Fat16_Deinit();
1649
                                        return(EOF);
1648
                                        return(EOF);
1650
                                }
1649
                                }
1651
                        }
1650
                        }
1652
                        file->SectorInCache     = file->DirectorySector;
1651
                        file->SectorInCache     = file->DirectorySector;
1653
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1652
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1654
                        {
1653
                        {
1655
                                Fat16_Deinit();
1654
                                Fat16_Deinit();
1656
                                return(EOF);
1655
                                return(EOF);
1657
                        }
1656
                        }
1658
 
1657
 
1659
                        dir = (DirEntry_t *)file->Cache;
1658
                        dir = (DirEntry_t *)file->Cache;
1660
                        // update file size and modification time & date
1659
                        // update file size and modification time & date
1661
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1660
                        dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);
1662
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1661
                        dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);
1663
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1662
                        dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate;
1664
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1663
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1665
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1664
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1666
                        {
1665
                        {
1667
                                Fat16_Deinit();
1666
                                Fat16_Deinit();
1668
                                return(EOF);
1667
                                return(EOF);
1669
                        }
1668
                        }
1670
                        break;
1669
                        break;
1671
                case 'r':
1670
                case 'r':
1672
                default:
1671
                default:
1673
                        // do nothing!
1672
                        // do nothing!
1674
                        return(EOF);
1673
                        return(EOF);
1675
                        break;
1674
                        break;
1676
 
1675
 
1677
        }
1676
        }
1678
        return(0);
1677
        return(0);
1679
}
1678
}
1680
 
1679
 
1681
/****************************************************************************************************************************************/
1680
/****************************************************************************************************************************************/
1682
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1681
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1683
/*                                                                                                                                                                                                                                                                              */
1682
/*                                                                                                                                                                                                                                                                              */
1684
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1683
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1685
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1684
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1686
/*                                                                                                                                                                                                                                                                              */
1685
/*                                                                                                                                                                                                                                                                              */
1687
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1686
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1688
/****************************************************************************************************************************************/
1687
/****************************************************************************************************************************************/
1689
s16 fclose_(File_t *file)
1688
s16 fclose_(File_t *file)
1690
{
1689
{
1691
        s16 returnvalue = EOF;
1690
        s16 returnvalue = EOF;
1692
 
1691
 
1693
        if(file == NULL) return(returnvalue);
1692
        if(file == NULL) return(returnvalue);
1694
        returnvalue = fflush_(file);
1693
        returnvalue = fflush_(file);
1695
        UnlockFilePointer(file);
1694
        UnlockFilePointer(file);
1696
        return(returnvalue);
1695
        return(returnvalue);
1697
}
1696
}
1698
 
1697
 
1699
/********************************************************************************************************************************************/
1698
/********************************************************************************************************************************************/
1700
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1699
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1701
/*                                                                                                                                                                                                                                                                                      */
1700
/*                                                                                                                                                                                                                                                                                      */
1702
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1701
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1703
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1702
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1704
/*                                                                                                                                                                                                                                                                                      */
1703
/*                                                                                                                                                                                                                                                                                      */
1705
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1704
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1706
/********************************************************************************************************************************************/
1705
/********************************************************************************************************************************************/
1707
s16 fgetc_(File_t *file)
1706
s16 fgetc_(File_t *file)
1708
{
1707
{
1709
        s16 c = EOF;
1708
        s16 c = EOF;
1710
        u32 curr_sector;
1709
        u32 curr_sector;
1711
 
1710
 
1712
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1711
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1713
        // if the end of the file is not reached, get the next character.
1712
        // if the end of the file is not reached, get the next character.
1714
        if((0 < file->Size) && ((file->Position) < file->Size) )
1713
        if((0 < file->Size) && ((file->Position) < file->Size) )
1715
        {
1714
        {
1716
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1715
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1717
                curr_sector += file->SectorOfCurrCluster;
1716
                curr_sector += file->SectorOfCurrCluster;
1718
 
1717
 
1719
                if(file->SectorInCache != curr_sector)
1718
                if(file->SectorInCache != curr_sector)
1720
                {
1719
                {
1721
                        file->SectorInCache = curr_sector;
1720
                        file->SectorInCache = curr_sector;
1722
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1721
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1723
                        {
1722
                        {
1724
                                Fat16_Deinit();
1723
                                Fat16_Deinit();
1725
                                return(c);
1724
                                return(c);
1726
                        }
1725
                        }
1727
                }
1726
                }
1728
                c = (s16) file->Cache[file->ByteOfCurrSector];
1727
                c = (s16) file->Cache[file->ByteOfCurrSector];
1729
                file->Position++;                                                                       // increment file position
1728
                file->Position++;                                                                       // increment file position
1730
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1729
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1731
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1730
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1732
                {
1731
                {
1733
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1732
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1734
                        file->SectorOfCurrCluster++;                                    //      next sector
1733
                        file->SectorOfCurrCluster++;                                    //      next sector
1735
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1734
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1736
                        {
1735
                        {
1737
 
1736
 
1738
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1737
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1739
                                {
1738
                                {
1740
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1739
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1741
                                }
1740
                                }
1742
                                else // the last cluster was allready reached
1741
                                else // the last cluster was allready reached
1743
                                {
1742
                                {
1744
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1743
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1745
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1744
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1746
                                }
1745
                                }
1747
                        }
1746
                        }
1748
                }
1747
                }
1749
        }
1748
        }
1750
        return(c);
1749
        return(c);
1751
}
1750
}
1752
 
1751
 
1753
/********************************************************************************************************************************************/
1752
/********************************************************************************************************************************************/
1754
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1753
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1755
/*                                                                                                                                                                                                                                                                                      */
1754
/*                                                                                                                                                                                                                                                                                      */
1756
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1755
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1757
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1756
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1758
/*                                                                                                                                                                                                                                                                                      */
1757
/*                                                                                                                                                                                                                                                                                      */
1759
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1758
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1760
/********************************************************************************************************************************************/
1759
/********************************************************************************************************************************************/
1761
s16 fputc_(const s8 c, File_t *file)
1760
s16 fputc_(const s8 c, File_t *file)
1762
{
1761
{
1763
        u32 curr_sector  = 0;
1762
        u32 curr_sector  = 0;
1764
 
1763
 
1765
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1764
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1766
        switch(file->Mode)
1765
        switch(file->Mode)
1767
        {
1766
        {
1768
                case 'w':
1767
                case 'w':
1769
                case 'a':
1768
                case 'a':
1770
                        // If file position equals to file size, then the end of file has been reached.
1769
                        // If file position equals to file size, then the end of file has been reached.
1771
                        // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1770
                        // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1772
                        // and a new cluster should be appended.
1771
                        // and a new cluster should be appended.
1773
                        // If the first sector of first cluster is unvalid, then the file claims no data clusters 
1772
                        // If the first sector of first cluster is unvalid, then the file claims no data clusters 
1774
                        // and size should be zero, therefore append a new Cluster too.
1773
                        // and size should be zero, therefore append a new Cluster too.
1775
                        if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED))
1774
                        if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED))
1776
                        {
1775
                        {
1777
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1776
                                if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF);
1778
                        }
1777
                        }
1779
               
1778
               
1780
                        curr_sector  = file->FirstSectorOfCurrCluster;
1779
                        curr_sector  = file->FirstSectorOfCurrCluster;
1781
                        curr_sector += file->SectorOfCurrCluster;
1780
                        curr_sector += file->SectorOfCurrCluster;
1782
                        if(file->SectorInCache != curr_sector)
1781
                        if(file->SectorInCache != curr_sector)
1783
                        {
1782
                        {
1784
                                file->SectorInCache = curr_sector;
1783
                                file->SectorInCache = curr_sector;
1785
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1784
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1786
                                {
1785
                                {
1787
                                        Fat16_Deinit();
1786
                                        Fat16_Deinit();
1788
                                        return(EOF);
1787
                                        return(EOF);
1789
                                }
1788
                                }
1790
                        }
1789
                        }
1791
               
1790
               
1792
                        file->Cache[file->ByteOfCurrSector] = (u8)c;            // write databyte into the buffer. The byte will be written to the device at once
1791
                        file->Cache[file->ByteOfCurrSector] = (u8)c;            // write databyte into the buffer. The byte will be written to the device at once
1793
                        if(file->Size == file->Position) file->Size++;          // a character has been written to the file so the size is incremented only when the character has been added at the end of the file.
1792
                        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.
1794
                        file->Position++;                                                                       // the actual positon within the file.
1793
                        file->Position++;                                                                       // the actual positon within the file.
1795
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1794
                        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1796
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1795
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1797
                        {       // save the sector to the sd-card
1796
                        {       // save the sector to the sd-card
1798
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1797
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1799
                                {
1798
                                {
1800
                                        Fat16_Deinit();
1799
                                        Fat16_Deinit();
1801
                                        return(EOF);
1800
                                        return(EOF);
1802
                                }
1801
                                }
1803
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1802
                                file->ByteOfCurrSector = 0;                                             //  reset byte location
1804
                                file->SectorOfCurrCluster++;                                    //      next sector
1803
                                file->SectorOfCurrCluster++;                                    //      next sector
1805
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1804
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1806
                                {
1805
                                {
1807
                                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1806
                                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1808
                                        { // if current cluster was the last cluster of the file
1807
                                        { // if current cluster was the last cluster of the file
1809
                                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1808
                                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1810
                                                {
1809
                                                {
1811
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1810
                                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1812
                                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1811
                                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1813
                                                        return(EOF);
1812
                                                        return(EOF);
1814
                                                }
1813
                                                }
1815
                                        }
1814
                                        }
1816
                                        else // next cluster
1815
                                        else // next cluster
1817
                                        {
1816
                                        {
1818
                                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1817
                                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1819
                                        }
1818
                                        }
1820
                                }
1819
                                }
1821
                        }
1820
                        }
1822
                        break;
1821
                        break;
1823
                case 'r':
1822
                case 'r':
1824
                default:
1823
                default:
1825
                        return(EOF);
1824
                        return(EOF);
1826
                        break;
1825
                        break;
1827
        } // EOF switch(file->Mode)
1826
        } // EOF switch(file->Mode)
1828
        return(0);
1827
        return(0);
1829
}
1828
}
1830
 
1829
 
1831
 
1830
 
1832
/****************************************************************************************************************************************/
1831
/****************************************************************************************************************************************/
1833
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1832
/*      Function:               fread_(void *buffer, s32 size, s32 count, File *File);                                                                                                                          */
1834
/*                                                                                                                                                                                                                                                                              */
1833
/*                                                                                                                                                                                                                                                                              */
1835
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1834
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1836
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1835
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1837
/*                                                                                                                                                                                                                                                                              */
1836
/*                                                                                                                                                                                                                                                                              */
1838
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1837
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1839
/****************************************************************************************************************************************/
1838
/****************************************************************************************************************************************/
1840
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1839
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
1841
{
1840
{
1842
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1841
        u32 object_cnt  = 0;                                                                                    // count the number of objects read from the file.
1843
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1842
        u32 object_size = 0;                                                                                    // count the number of bytes read from the actual object.
1844
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1843
        u8 *pbuff       = 0;                                                                                    // a pointer to the actual bufferposition.
1845
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1844
        u8 success      = 1;                                                                                    // no error occured during read operation to the file.
1846
        s16 c;
1845
        s16 c;
1847
 
1846
 
1848
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1847
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1849
 
1848
 
1850
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1849
        pbuff = (u8 *) buffer;                                                                                  // cast the void pointer to an u8 *
1851
 
1850
 
1852
        while((object_cnt < count) && success)
1851
        while((object_cnt < count) && success)
1853
        {
1852
        {
1854
                object_size = size;
1853
                object_size = size;
1855
                while((size > 0) && success)
1854
                while((size > 0) && success)
1856
                {
1855
                {
1857
                        c = fgetc_(file);
1856
                        c = fgetc_(file);
1858
                        if(c != EOF)
1857
                        if(c != EOF)
1859
                        {
1858
                        {
1860
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1859
                                *pbuff = (u8)c;                                                                         // read a byte from the buffer to the opened file.
1861
                                pbuff++;
1860
                                pbuff++;
1862
                                size--;
1861
                                size--;
1863
                        }
1862
                        }
1864
                        else // error or end of file reached
1863
                        else // error or end of file reached
1865
                        {
1864
                        {
1866
                                success = 0;
1865
                                success = 0;
1867
                        }
1866
                        }
1868
                }
1867
                }
1869
                if(success) object_cnt++;
1868
                if(success) object_cnt++;
1870
        }
1869
        }
1871
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1870
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1872
}
1871
}
1873
 
1872
 
1874
 
1873
 
1875
/****************************************************************************************************************************************/
1874
/****************************************************************************************************************************************/
1876
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1875
/*      Function:               fwrite_(void *buffer, s32 size, s32 count, File *file);                                                                                                                         */
1877
/*                                                                                                                                                                                                                                                                              */
1876
/*                                                                                                                                                                                                                                                                              */
1878
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1877
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1879
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1878
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1880
/*                                                                                                                                                                                                                                                                              */
1879
/*                                                                                                                                                                                                                                                                              */
1881
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1880
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1882
/****************************************************************************************************************************************/
1881
/****************************************************************************************************************************************/
1883
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
1882
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
1884
{
1883
{
1885
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1884
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
1886
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
1885
        u32 object_size = 0;                                                                                                            // count the number of bytes written from the actual object.
1887
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1886
        u8 *pbuff           = 0;                                                                                                                // a pointer to the actual bufferposition.
1888
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1887
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
1889
        s16 c;
1888
        s16 c;
1890
 
1889
 
1891
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1890
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1892
        if(file->Mode == 'r') return (0); // opened read only
1891
        if(file->Mode == 'r') return (0); // opened read only
1893
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1892
        pbuff = (u8 *) buffer;                                                                                                          // cast the void pointer to an u8 *
1894
 
1893
 
1895
        while((object_cnt < count) && success)
1894
        while((object_cnt < count) && success)
1896
        {
1895
        {
1897
                object_size = size;
1896
                object_size = size;
1898
                while((size > 0) && success)
1897
                while((size > 0) && success)
1899
                {
1898
                {
1900
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1899
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1901
                        if(c != EOF)
1900
                        if(c != EOF)
1902
                        {
1901
                        {
1903
                                pbuff++;
1902
                                pbuff++;
1904
                                size--;
1903
                                size--;
1905
                        }
1904
                        }
1906
                        else
1905
                        else
1907
                        {
1906
                        {
1908
                                success = 0;
1907
                                success = 0;
1909
                        }
1908
                        }
1910
                }
1909
                }
1911
                if(success) object_cnt++;
1910
                if(success) object_cnt++;
1912
        }
1911
        }
1913
 
1912
 
1914
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1913
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1915
}
1914
}
1916
 
1915
 
1917
 
1916
 
1918
/****************************************************************************************************************************************/
1917
/****************************************************************************************************************************************/
1919
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1918
/*      Function:               fputs_(const s8 *string, File_t *File);                                                                                                                                                         */
1920
/*                                                                                                                                                                                                                                                                              */
1919
/*                                                                                                                                                                                                                                                                              */
1921
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1920
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1922
/*                                                                                                                                                                                                                                                                              */
1921
/*                                                                                                                                                                                                                                                                              */
1923
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1922
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1924
/****************************************************************************************************************************************/
1923
/****************************************************************************************************************************************/
1925
s16 fputs_(s8 * const string, File_t * const file)
1924
s16 fputs_(s8 * const string, File_t * const file)
1926
{
1925
{
1927
        u8 i=0;
1926
        u8 i=0;
1928
        s16 c = 0;
1927
        s16 c = 0;
1929
 
1928
 
1930
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
1929
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF);
1931
        if(file->Mode == 'r') return(EOF);
1930
        if(file->Mode == 'r') return(EOF);
1932
        while((string[i] != 0)&& (c != EOF))
1931
        while((string[i] != 0)&& (c != EOF))
1933
        {
1932
        {
1934
                c = fputc_(string[i], file);
1933
                c = fputc_(string[i], file);
1935
                i++;
1934
                i++;
1936
        }
1935
        }
1937
        return(c);
1936
        return(c);
1938
}
1937
}
1939
 
1938
 
1940
/****************************************************************************************************************************************/
1939
/****************************************************************************************************************************************/
1941
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
1940
/*      Function:               fgets_(s8 *, s16 , File_t *);                                                                                                                                                                           */
1942
/*                                                                                                                                                                                                                                                                              */
1941
/*                                                                                                                                                                                                                                                                              */
1943
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1942
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1944
/*                                                                                                                                                                                                                                                                              */
1943
/*                                                                                                                                                                                                                                                                              */
1945
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1944
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1946
/****************************************************************************************************************************************/
1945
/****************************************************************************************************************************************/
1947
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
1946
s8 * fgets_(s8 * const string, s16 const length, File_t * const file)
1948
{
1947
{
1949
        s8 *pbuff;
1948
        s8 *pbuff;
1950
        s16 c = 0, bytecount;
1949
        s16 c = 0, bytecount;
1951
 
1950
 
1952
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
1951
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0);
1953
        bytecount = length;
1952
        bytecount = length;
1954
        pbuff = string;                                                         // set write pointer to start of string
1953
        pbuff = string;                                                         // set write pointer to start of string
1955
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
1954
        while(bytecount > 1)                                            // read the length-1 characters from the file to the string.
1956
        {
1955
        {
1957
                c = fgetc_(file);                                               // read a character from the opened file.
1956
                c = fgetc_(file);                                               // read a character from the opened file.
1958
                switch(c)
1957
                switch(c)
1959
                {
1958
                {
1960
                        case 0x0A:                                                      // new line
1959
                        case 0x0A:                                                      // new line
1961
                                *pbuff = 0;                                             // set string terminator
1960
                                *pbuff = 0;                                             // set string terminator
1962
                                return(string);                                 // return normal
1961
                                return(string);                                 // return normal
1963
 
1962
 
1964
                        case EOF:
1963
                        case EOF:
1965
                                *pbuff = 0;                                             // set string terminator
1964
                                *pbuff = 0;                                             // set string terminator
1966
                                return(0);
1965
                                return(0);
1967
 
1966
 
1968
                        default:
1967
                        default:
1969
                                *pbuff++ = (s8)c;                               // copy byte to string
1968
                                *pbuff++ = (s8)c;                               // copy byte to string
1970
                                bytecount--;
1969
                                bytecount--;
1971
                                break;
1970
                                break;
1972
                }
1971
                }
1973
        }
1972
        }
1974
        *pbuff = 0;     // set string terminator
1973
        *pbuff = 0;     // set string terminator
1975
        return(string);
1974
        return(string);
1976
}
1975
}
1977
 
1976
 
1978
/****************************************************************************************************************************************/
1977
/****************************************************************************************************************************************/
1979
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
1978
/*      Function:               fexist_(const u8*);                                                                                                                                                                                                     */
1980
/*                                                                                                                                                                                                                                                                              */
1979
/*                                                                                                                                                                                                                                                                              */
1981
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1980
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1982
/*                                                                                                                                                                                                                                                                              */
1981
/*                                                                                                                                                                                                                                                                              */
1983
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1982
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1984
/****************************************************************************************************************************************/
1983
/****************************************************************************************************************************************/
1985
u8 fexist_(s8 * const filename)
1984
u8 fexist_(s8 * const filename)
1986
{
1985
{
1987
        u8 exist = 0;
1986
        u8 exist = 0;
1988
        File_t *file = 0;
1987
        File_t *file = 0;
1989
        file = LockFilePointer();
1988
        file = LockFilePointer();
1990
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1989
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1991
        UnlockFilePointer(file);
1990
        UnlockFilePointer(file);
1992
        return(exist);
1991
        return(exist);
1993
}
1992
}
1994
 
1993
 
1995
/****************************************************************************************************************************************/
1994
/****************************************************************************************************************************************/
1996
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1995
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1997
/*                                                                                                                                                                                                                                                                              */
1996
/*                                                                                                                                                                                                                                                                              */
1998
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1997
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1999
/*                                                                                                                                                                                                                                                                              */
1998
/*                                                                                                                                                                                                                                                                              */
2000
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1999
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
2001
/****************************************************************************************************************************************/
2000
/****************************************************************************************************************************************/
2002
u8 feof_(File_t *file)
2001
u8 feof_(File_t *file)
2003
{
2002
{
2004
        if(((file->Position)+1) < (file->Size))
2003
        if(((file->Position)+1) < (file->Size))
2005
        {
2004
        {
2006
                return(0);
2005
                return(0);
2007
        }
2006
        }
2008
        else
2007
        else
2009
        {
2008
        {
2010
                return(1);
2009
                return(1);
2011
        }
2010
        }
2012
}
2011
}
2013
 
2012
 
2014
/****************************************************************************************************************************************************/
2013
/****************************************************************************************************************************************************/
2015
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
2014
/* Function:    s8* FAT16_GetVolumeLabel(void)                                                                                                                                                                                                                  */
2016
/*                                                                                                                                                                                                                                                                                                      */
2015
/*                                                                                                                                                                                                                                                                                                      */
2017
/* Description: This function returns the volume label                                                                                                                                                                                          */
2016
/* Description: This function returns the volume label                                                                                                                                                                                          */
2018
/*                                                                                                                                                                                                                                                                                                      */
2017
/*                                                                                                                                                                                                                                                                                                      */
2019
/* Returnvalue: This function returns the pointer to the volume label or NULL if not found.                                                                                                                     */
2018
/* Returnvalue: This function returns the pointer to the volume label or NULL if not found.                                                                                                                     */
2020
/****************************************************************************************************************************************************/
2019
/****************************************************************************************************************************************************/
2021
s8* FAT16_GetVolumeLabel(void)
2020
s8* FAT16_GetVolumeLabel(void)
2022
{
2021
{
2023
        s8              *pVolumeLabel = NULL;
2022
        s8              *pVolumeLabel = NULL;
2024
        u32             dir_sector, max_dir_sector, curr_sector;
2023
        u32             dir_sector, max_dir_sector, curr_sector;
2025
        u16     dir_entry = 0;
2024
        u16     dir_entry = 0;
2026
        u8              i = 0;
2025
        u8              i = 0;
2027
 
2026
 
2028
        DirEntry_t * dir;
2027
        DirEntry_t * dir;
2029
        File_t *file = NULL;
2028
        File_t *file = NULL;
2030
       
2029
       
2031
        // if Partition is not valud return NULL
2030
        // if Partition is not valud return NULL
2032
        if(!Partition.IsValid) return(pVolumeLabel);
2031
        if(!Partition.IsValid) return(pVolumeLabel);
2033
        // if Volume label was read before return it
2032
        // if Volume label was read before return it
2034
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
2033
        if(Partition.VolumeLabel[0]!= '\0') return (Partition.VolumeLabel);
2035
        // try to catch a file pointer
2034
        // try to catch a file pointer
2036
        file = LockFilePointer();
2035
        file = LockFilePointer();
2037
        if(file == NULL) return(pVolumeLabel);
2036
        if(file == NULL) return(pVolumeLabel);
2038
        // search dir entries direct within the root directory area
2037
        // search dir entries direct within the root directory area
2039
        file->DirectorySector = 0;
2038
        file->DirectorySector = 0;
2040
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2039
        max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2041
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
2040
        file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
2042
       
2041
       
2043
        // update current file data area position to start of first cluster
2042
        // update current file data area position to start of first cluster
2044
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2043
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
2045
        file->SectorOfCurrCluster               = 0;
2044
        file->SectorOfCurrCluster               = 0;
2046
        file->ByteOfCurrSector                  = 0;
2045
        file->ByteOfCurrSector                  = 0;
2047
 
2046
 
2048
        dir_sector = 0; // reset sector counter within a new cluster
2047
        dir_sector = 0; // reset sector counter within a new cluster
2049
        do // loop over all sectors of the root directory
2048
        do // loop over all sectors of the root directory
2050
        {
2049
        {
2051
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2050
                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
2052
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2051
                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
2053
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
2052
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
2054
                {
2053
                {
2055
                        Fat16_Deinit();
2054
                        Fat16_Deinit();
2056
                        return(pVolumeLabel);
2055
                        return(pVolumeLabel);
2057
                }
2056
                }
2058
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2057
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
2059
                // search all directory entries within that sector
2058
                // search all directory entries within that sector
2060
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2059
                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
2061
                {   // check for existing dir entry
2060
                {   // check for existing dir entry
2062
                        switch((u8)dir[dir_entry].Name[0])
2061
                        switch((u8)dir[dir_entry].Name[0])
2063
                        {
2062
                        {
2064
                                case SLOT_EMPTY:
2063
                                case SLOT_EMPTY:
2065
                                case SLOT_DELETED:
2064
                                case SLOT_DELETED:
2066
                                        // ignore empty or deleted dir entries
2065
                                        // ignore empty or deleted dir entries
2067
                                        break;
2066
                                        break;
2068
                                default:
2067
                                default:
2069
                                        // check attributes for volume label
2068
                                        // check attributes for volume label
2070
                                        if ((dir[dir_entry].Attribute & ATTR_VOLUMELABEL) != ATTR_VOLUMELABEL) break; // attribute must match
2069
                                        if ((dir[dir_entry].Attribute & ATTR_VOLUMELABEL) != ATTR_VOLUMELABEL) break; // attribute must match
2071
                                        // (first 11 characters include 8 chars of basename and 3 chars extension.)
2070
                                        // (first 11 characters include 8 chars of basename and 3 chars extension.)
2072
                                        for(i = 0; i<11;i++) Partition.VolumeLabel[i] = dir[dir_entry].Name[i];
2071
                                        for(i = 0; i<11;i++) Partition.VolumeLabel[i] = dir[dir_entry].Name[i];
2073
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2072
                                        Partition.VolumeLabel[11] = '\0'; // terminate string
2074
                                        file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
2073
                                        file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
2075
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
2074
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
2076
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2075
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
2077
                                        file->SectorOfCurrCluster = 0;
2076
                                        file->SectorOfCurrCluster = 0;
2078
                                        file->ByteOfCurrSector = 0;
2077
                                        file->ByteOfCurrSector = 0;
2079
                                        file->DirectorySector = curr_sector; // current sector
2078
                                        file->DirectorySector = curr_sector; // current sector
2080
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2079
                                        file->DirectoryIndex  = dir_entry; // current direntry in current sector
2081
                                        file->Size = dir[dir_entry].Size;
2080
                                        file->Size = dir[dir_entry].Size;
2082
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2081
                                        dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
2083
                                        pVolumeLabel =  Partition.VolumeLabel;
2082
                                        pVolumeLabel =  Partition.VolumeLabel;
2084
                        } // end of first byte of name check
2083
                        } // end of first byte of name check
2085
                }
2084
                }
2086
                dir_sector++; // search next sector
2085
                dir_sector++; // search next sector
2087
        // stop if we reached the end of the cluster or the end of the root dir
2086
        // stop if we reached the end of the cluster or the end of the root dir
2088
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2087
        }while((dir_sector < max_dir_sector) && (!pVolumeLabel));
2089
 
2088
 
2090
        UnlockFilePointer(file);
2089
        UnlockFilePointer(file);
2091
        return(pVolumeLabel);
2090
        return(pVolumeLabel);
2092
}
2091
}
2093
 
2092
 
2094
 
2093
 
2095
 
2094
 
2096
#define ATTR_NONE               0x00    // normal file
2095
#define ATTR_NONE               0x00    // normal file
2097
#define ATTR_READONLY           0x01    // file is readonly
2096
#define ATTR_READONLY           0x01    // file is readonly
2098
#define ATTR_HIDDEN                     0x02    // file is hidden
2097
#define ATTR_HIDDEN                     0x02    // file is hidden
2099
#define ATTR_SYSTEM                     0x04    // file is a system file
2098
#define ATTR_SYSTEM                     0x04    // file is a system file
2100
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
2099
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
2101
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
2100
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
2102
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
2101
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
2103
#define ATTR_ARCHIVE            0x20    // file is new or modified
2102
#define ATTR_ARCHIVE            0x20    // file is new or modified
2104
 
2103
 
2105
 
2104
 
2106
/********************************************************************************************************************************************/
2105
/********************************************************************************************************************************************/
2107
/*      Function:               u8 FindItem(Find_t);                                                                                                                                                                                                                    */
2106
/*      Function:               u8 FindItem(Find_t);                                                                                                                                                                                                                    */
2108
/*                                                                                                                                                                                                                                                                                      */
2107
/*                                                                                                                                                                                                                                                                                      */
2109
/*      Description:    This function looks for the item specified by global structure FindElement in the actual directory                                      */
2108
/*      Description:    This function looks for the item specified by global structure FindElement in the actual directory                                      */
2110
/*                                                                                                                                                                                                                                                              */
2109
/*                                                                                                                                                                                                                                                              */
2111
/*                                                                                                                                                                                                                                                                                      */
2110
/*                                                                                                                                                                                                                                                                                      */
2112
/*      Returnvalue:    TRUE if an matching element was found                                                                                                                                                                           */
2111
/*      Returnvalue:    TRUE if an matching element was found                                                                                                                                                                           */
2113
/********************************************************************************************************************************************/
2112
/********************************************************************************************************************************************/
2114
 
2113
 
2115
u8 FindItem(Find_t *findelement)
2114
u8 FindItem(Find_t *findelement)
2116
{
2115
{
2117
        u16             index = 0;
2116
        u16             index = 0;
2118
        u16             max_dir_sector = 0;
2117
        u16             max_dir_sector = 0;
2119
        u16     end_of_directory_not_reached = 1;                                                                               // the directory has been read completely without a result.
2118
        u16     end_of_directory_not_reached = 1;                                                                               // the directory has been read completely without a result.
2120
        u8              i = 0;
2119
        u8              i = 0;
2121
        u8              readpointer = 0;
2120
        u8              readpointer = 0;
2122
        u8              writepointer = 0;
2121
        u8              writepointer = 0;
2123
        u8              retvalue = 0;
2122
        u8              retvalue = 0;
2124
        DirEntry_t      *DirectoryEntry;
2123
        DirEntry_t      *DirectoryEntry;
2125
        File_t  file;
2124
        File_t  file;
2126
 
2125
 
2127
        file.FirstSectorOfCurrCluster   = findelement->fp.FirstSectorOfCurrCluster;
2126
        file.FirstSectorOfCurrCluster   = findelement->fp.FirstSectorOfCurrCluster;
2128
        file.SectorOfCurrCluster        = findelement->fp.SectorOfCurrCluster;
2127
        file.SectorOfCurrCluster        = findelement->fp.SectorOfCurrCluster;
2129
        index                                                   = findelement->fp.DirectoryIndex;
2128
        index                                                   = findelement->fp.DirectoryIndex;
2130
 
2129
 
2131
        // within the root directory area we can read sectors sequentially until the end of this area
2130
        // within the root directory area we can read sectors sequentially until the end of this area
2132
        if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector))
2131
        if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector))
2133
        {
2132
        {
2134
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2133
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
2135
        }
2134
        }
2136
        // within the data clusters we can read sectors sequentially only within the cluster
2135
        // within the data clusters we can read sectors sequentially only within the cluster
2137
        else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector))
2136
        else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector))
2138
        {
2137
        {
2139
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
2138
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
2140
        }
2139
        }
2141
 
2140
 
2142
        do
2141
        do
2143
        {                                                                                                                                                               // search the next 16 rootentries in this sector of the roordirectory.          
2142
        {                                                                                                                                                               // search the next 16 rootentries in this sector of the roordirectory.          
2144
                SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache);                                               // Read the Rootdirectory.
2143
                SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache);                                               // Read the Rootdirectory.
2145
                DirectoryEntry = (DirEntry_t *)file.Cache;
2144
                DirectoryEntry = (DirEntry_t *)file.Cache;
2146
 
2145
 
2147
                while((!retvalue)&&(index<16))
2146
                while((!retvalue)&&(index<16))
2148
                {
2147
                {
2149
                        i=0;                   
2148
                        i=0;                   
2150
                        if((u8) DirectoryEntry[index].Name[0] != 0xe5)                                                          // ignore deleted items.
2149
                        if((u8) DirectoryEntry[index].Name[0] != 0xe5)                                                          // ignore deleted items.
2151
                        {
2150
                        {
2152
                                while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?'))
2151
                                while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?'))
2153
                                {
2152
                                {
2154
                                        i++;
2153
                                        i++;
2155
                                }
2154
                                }
2156
                        }
2155
                        }
2157
                        if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11))
2156
                        if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11))
2158
                        {
2157
                        {
2159
                for(readpointer=0;readpointer<=10;readpointer++)
2158
                for(readpointer=0;readpointer<=10;readpointer++)
2160
                                {
2159
                                {
2161
                                        if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
2160
                                        if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
2162
                                        {
2161
                                        {
2163
                                                findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2162
                                                findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2164
                                                writepointer++;
2163
                                                writepointer++;
2165
                                        }
2164
                                        }
2166
                                        else  
2165
                                        else  
2167
                                        {
2166
                                        {
2168
                                                if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)                                            
2167
                                                if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)                                            
2169
                                                {
2168
                                                {
2170
                                        if(readpointer < 8) readpointer=8;
2169
                                        if(readpointer < 8) readpointer=8;
2171
                                        if(DirectoryEntry[index].Name[readpointer] != ' ')
2170
                                        if(DirectoryEntry[index].Name[readpointer] != ' ')
2172
                                        {
2171
                                        {
2173
                                        findelement->name[writepointer] = '.';                                                  // then seperate the name and the extension by a '.' at index 8.                                                
2172
                                        findelement->name[writepointer] = '.';                                                  // then seperate the name and the extension by a '.' at index 8.                                                
2174
                                        writepointer++;
2173
                                        writepointer++;
2175
                                        findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2174
                                        findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer];      // copy the name of the item found to the find_structure.
2176
                                        writepointer++;
2175
                                        writepointer++;
2177
                                        }
2176
                                        }
2178
                                            else break;
2177
                                            else break;
2179
                                                }
2178
                                                }
2180
                            else break;
2179
                            else break;
2181
                        }
2180
                        }
2182
                        /* terminate the namestring with 0 for debugpurposes*/
2181
                        /* terminate the namestring with 0 for debugpurposes*/
2183
                        findelement->name[12] = 0;
2182
                        findelement->name[12] = 0;
2184
                                }
2183
                                }
2185
                                findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;                                                  
2184
                                findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;                                                  
2186
                                findelement->fp.DirectoryIndex   = index;              
2185
                                findelement->fp.DirectoryIndex   = index;              
2187
                                findelement->fp.FirstSectorOfCurrCluster   = file.FirstSectorOfCurrCluster;
2186
                                findelement->fp.FirstSectorOfCurrCluster   = file.FirstSectorOfCurrCluster;
2188
                                findelement->fp.DirectorySector  = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
2187
                                findelement->fp.DirectorySector  = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
2189
                                findelement->fp.SectorOfCurrCluster      = file.SectorOfCurrCluster;
2188
                                findelement->fp.SectorOfCurrCluster      = file.SectorOfCurrCluster;
2190
                findelement->fp.Size            = DirectoryEntry[index].Size;
2189
                findelement->fp.Size            = DirectoryEntry[index].Size;
2191
                                findelement->fp.Attribute               = DirectoryEntry[index].Attribute;
2190
                                findelement->fp.Attribute               = DirectoryEntry[index].Attribute;
2192
                retvalue = 1;
2191
                retvalue = 1;
2193
                        }                      
2192
                        }                      
2194
                        /* search the next sector */
2193
                        /* search the next sector */
2195
                        index++;
2194
                        index++;
2196
                }
2195
                }
2197
                /* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */
2196
                /* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */
2198
                if(!retvalue)                                                                                                                           // file not found in this sector so take next sector.
2197
                if(!retvalue)                                                                                                                           // file not found in this sector so take next sector.
2199
                {
2198
                {
2200
                        /* in the next sector we start looking for the specified entry beginning at index 0 */
2199
                        /* in the next sector we start looking for the specified entry beginning at index 0 */
2201
                        index = 0;
2200
                        index = 0;
2202
                        /* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */
2201
                        /* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */
2203
                        if(file.SectorOfCurrCluster < max_dir_sector-1)  file.SectorOfCurrCluster++; else end_of_directory_not_reached = 0;
2202
                        if(file.SectorOfCurrCluster < max_dir_sector-1)  file.SectorOfCurrCluster++; else end_of_directory_not_reached = 0;
2204
                        /* if we are looking for an directoryentry outside the rootdirectory and have reached the end of the cluster we have to get the next one */
2203
                        /* 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 */
2205
                        if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster)
2204
                        if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster)
2206
                        {
2205
                        {
2207
                                end_of_directory_not_reached = GetNextCluster(&file);
2206
                                end_of_directory_not_reached = GetNextCluster(&file);
2208
                        }
2207
                        }
2209
                }
2208
                }
2210
        }
2209
        }
2211
        while((end_of_directory_not_reached) && (!retvalue));
2210
        while((end_of_directory_not_reached) && (!retvalue));
2212
 
2211
 
2213
        return(retvalue);      
2212
        return(retvalue);      
2214
}
2213
}
2215
 
2214
 
2216
 
2215
 
2217
 
2216
 
2218
 
2217
 
2219
/********************************************************************************************************************************************/
2218
/********************************************************************************************************************************************/
2220
/*      Function:               findnext_(Find_t *);                                                                                                                                                                                                                    */
2219
/*      Function:               findnext_(Find_t *);                                                                                                                                                                                                                    */
2221
/*                                                                                                                                                                                                                                                                                      */
2220
/*                                                                                                                                                                                                                                                                                      */
2222
/*      Description:    This function looks for the next item in the specified directory with a matching filename and fileattributes specified  */
2221
/*      Description:    This function looks for the next item in the specified directory with a matching filename and fileattributes specified  */
2223
/*                  by function findfirst()                                                                                                                                                                                                     */
2222
/*                  by function findfirst()                                                                                                                                                                                                     */
2224
/*                                                                                                                                                                                                                                                                                      */
2223
/*                                                                                                                                                                                                                                                                                      */
2225
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2224
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2226
/********************************************************************************************************************************************/
2225
/********************************************************************************************************************************************/
2227
u8 findnext_(Find_t * findelement)
2226
u8 findnext_(Find_t * findelement)
2228
{
2227
{
2229
        u8 itemfound = 0;
2228
        u8 itemfound = 0;
2230
        u8 index = 0;
2229
        u8 index = 0;
2231
 
2230
 
2232
        findelement->fp.DirectoryIndex++;
2231
        findelement->fp.DirectoryIndex++;
2233
 
2232
 
2234
        /* before we start searching an element we clear the complete namestring within the structure FindElement */
2233
        /* before we start searching an element we clear the complete namestring within the structure FindElement */
2235
        for(index=0;index<11;index++) findelement->name[index] = 0;
2234
        for(index=0;index<11;index++) findelement->name[index] = 0;
2236
 
2235
 
2237
        if(FindItem(findelement))
2236
        if(FindItem(findelement))
2238
        {
2237
        {
2239
                itemfound = 1;         
2238
                itemfound = 1;         
2240
        }
2239
        }
2241
 
2240
 
2242
        return(itemfound);
2241
        return(itemfound);
2243
}
2242
}
2244
 
2243
 
2245
 
2244
 
2246
 
2245
 
2247
/********************************************************************************************************************************************/
2246
/********************************************************************************************************************************************/
2248
/*      Function:               findfirst_(s8* filename, u8 attribmask, Find_t *);                                                                                                                                              */
2247
/*      Function:               findfirst_(s8* filename, u8 attribmask, Find_t *);                                                                                                                                              */
2249
/*                                                                                                                                                                                                                                                                                      */
2248
/*                                                                                                                                                                                                                                                                                      */
2250
/*      Description:    This function looks for the first item in the specified directory with a matching filename and fileattributes                   */
2249
/*      Description:    This function looks for the first item in the specified directory with a matching filename and fileattributes                   */
2251
/*                                      The filename of the element found is transformed from 8.3 to a string                                                                                                   */
2250
/*                                      The filename of the element found is transformed from 8.3 to a string                                                                                                   */
2252
/*                                                                                                                                                                                                                                                                                      */
2251
/*                                                                                                                                                                                                                                                                                      */
2253
/*                                                                                                                                                                                                                                                                                      */
2252
/*                                                                                                                                                                                                                                                                                      */
2254
/*      Returnvalue:    (1) if Element was found. (0) if no valid element was found                                                                                                                     */
2253
/*      Returnvalue:    (1) if Element was found. (0) if no valid element was found                                                                                                                     */
2255
/********************************************************************************************************************************************/
2254
/********************************************************************************************************************************************/
2256
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
2255
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
2257
{
2256
{
2258
        u8 itemfound = 0;
2257
        u8 itemfound = 0;
2259
        u8 index = 0;  
2258
        u8 index = 0;  
2260
 
2259
 
2261
        /* initialize the FindElement structure */
2260
        /* initialize the FindElement structure */
2262
        findelement->fp.FirstSectorOfFirstCluster = 0;  // First sector of the first cluster of the file.
2261
        findelement->fp.FirstSectorOfFirstCluster = 0;  // First sector of the first cluster of the file.
2263
        findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory;                                   // First sector of the cluster which is edited at the moment.
2262
        findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory;                                   // First sector of the cluster which is edited at the moment.
2264
        findelement->fp.SectorOfCurrCluster = 0;                                                        // The sector within the current cluster.
2263
        findelement->fp.SectorOfCurrCluster = 0;                                                        // The sector within the current cluster.
2265
        findelement->fp.ByteOfCurrSector = 0;                                                   // The byte location within the current sector.
2264
        findelement->fp.ByteOfCurrSector = 0;                                                   // The byte location within the current sector.
2266
        findelement->fp.Size = 0;                                                                               // The size of the opend file in bytes.
2265
        findelement->fp.Size = 0;                                                                               // The size of the opend file in bytes.
2267
        findelement->fp.Position = 0;                                                                   // Pointer to a character within the file 0 < fileposition < filesize
2266
        findelement->fp.Position = 0;                                                                   // Pointer to a character within the file 0 < fileposition < filesize
2268
        findelement->fp.DirectorySector = 0;                                                            // the sectorposition where the directoryentry has been made.
2267
        findelement->fp.DirectorySector = 0;                                                            // the sectorposition where the directoryentry has been made.
2269
        findelement->fp.DirectoryIndex = 0;                                                             // The index to the directoryentry within the specified sector.
2268
        findelement->fp.DirectoryIndex = 0;                                                             // The index to the directoryentry within the specified sector.
2270
        findelement->attribfilter = 0;
2269
        findelement->attribfilter = 0;
2271
        findelement->attribmask = attribmask;
2270
        findelement->attribmask = attribmask;
2272
        findelement->searchstring[0]=0;
2271
        findelement->searchstring[0]=0;
2273
 
2272
 
2274
        /* seperate the name of the element to be found from the filepath and bring it to the 8.3*/
2273
        /* seperate the name of the element to be found from the filepath and bring it to the 8.3*/
2275
        SeperateDirName(name, findelement->searchstring);
2274
        SeperateDirName(name, findelement->searchstring);
2276
        /* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */
2275
        /* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */
2277
        for(index=0;index<8;index++)
2276
        for(index=0;index<8;index++)
2278
        {
2277
        {
2279
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2278
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2280
                if(findelement->searchstring[index] == '*')
2279
                if(findelement->searchstring[index] == '*')
2281
                {
2280
                {
2282
                        /*  */
2281
                        /*  */
2283
                        while(++index <8) findelement->searchstring[index] = '*';
2282
                        while(++index <8) findelement->searchstring[index] = '*';
2284
                }
2283
                }
2285
        }
2284
        }
2286
        for(index=8;index<11;index++)
2285
        for(index=8;index<11;index++)
2287
        {                                                                                                                                                                                                                                        
2286
        {                                                                                                                                                                                                                                        
2288
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2287
                /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
2289
                if(findelement->searchstring[index] == '*')
2288
                if(findelement->searchstring[index] == '*')
2290
                {
2289
                {
2291
                        /*  */
2290
                        /*  */
2292
                        while(++index <11) findelement->searchstring[index] = '*';
2291
                        while(++index <11) findelement->searchstring[index] = '*';
2293
                }
2292
                }
2294
        }
2293
        }
2295
       
2294
       
2296
        /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */
2295
        /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */
2297
        findelement->fp.DirectoryIndex--;
2296
        findelement->fp.DirectoryIndex--;
2298
        /* now lets search for the item within the direcory */
2297
        /* now lets search for the item within the direcory */
2299
        itemfound = findnext_(findelement);
2298
        itemfound = findnext_(findelement);
2300
 
2299
 
2301
        return(itemfound);
2300
        return(itemfound);
2302
}
2301
}
2303
 
2302
 
2304
 
2303
 
2305
/********************************************************************************************************************************************/
2304
/********************************************************************************************************************************************/
2306
/*      Function:               u8 GetDirCount(s8* filepath);                                                                                                                                                                                   */
2305
/*      Function:               u8 GetDirCount(s8* filepath);                                                                                                                                                                                   */
2307
/*                                                                                                                                                                                                                                                                                      */
2306
/*                                                                                                                                                                                                                                                                                      */
2308
/*      Description:    This function counts the number of subdirectories the dirpath contains                                                                                                  */
2307
/*      Description:    This function counts the number of subdirectories the dirpath contains                                                                                                  */
2309
/*                                                                                                                                                                                                                                                              */
2308
/*                                                                                                                                                                                                                                                              */
2310
/*                                                                                                                                                                                                                                                                                      */
2309
/*                                                                                                                                                                                                                                                                                      */
2311
/*      Returnvalue:    then number of subdirectories within the specified path                                                                                                                                 */
2310
/*      Returnvalue:    then number of subdirectories within the specified path                                                                                                                                 */
2312
/********************************************************************************************************************************************/
2311
/********************************************************************************************************************************************/
2313
u8 GetDirCount(u8 *dirpath)
2312
u8 GetDirCount(u8 *dirpath)
2314
{
2313
{
2315
   u8 i=0;
2314
   u8 i=0;
2316
   u8 cnt=0;
2315
   u8 cnt=0;
2317
 
2316
 
2318
   while(dirpath[i] != 0)
2317
   while(dirpath[i] != 0)
2319
   {
2318
   {
2320
      if(dirpath[i]=='/')
2319
      if(dirpath[i]=='/')
2321
      {  
2320
      {  
2322
         if(dirpath[i+1]!=0) cnt++;                                            // ignore last'/'
2321
         if(dirpath[i+1]!=0) cnt++;                                            // ignore last'/'
2323
      }
2322
      }
2324
      i++;  
2323
      i++;  
2325
   }
2324
   }
2326
   i=0;  
2325
   i=0;  
2327
   return(cnt);
2326
   return(cnt);
2328
}
2327
}
2329
 
2328
 
2330
 
2329
 
2331
/********************************************************************************************************************************************/
2330
/********************************************************************************************************************************************/
2332
/* Funtion:     char *GetSubDirectory (char *dirpath, char *directory)                                                                                                                                          */
2331
/* Funtion:     char *GetSubDirectory (char *dirpath, char *directory)                                                                                                                                          */
2333
/*                                                                                                                                                                                                                                                                                      */
2332
/*                                                                                                                                                                                                                                                                                      */
2334
/* Description: this function returns a pointer to the beginning of the next subdirectory or NULL                                                                                       */
2333
/* Description: this function returns a pointer to the beginning of the next subdirectory or NULL                                                                                       */
2335
/*                                                                                                                                                                                                                                                                                      */
2334
/*                                                                                                                                                                                                                                                                                      */
2336
/*                                                                                                                                                                                                                                                                                      */
2335
/*                                                                                                                                                                                                                                                                                      */
2337
/* returnvalue:   number of subdirectories in the filepath                                                                                                                                                                      */
2336
/* returnvalue:   number of subdirectories in the filepath                                                                                                                                                                      */
2338
/********************************************************************************************************************************************/
2337
/********************************************************************************************************************************************/
2339
u8 * GetSubDirectory(u8 *dirpath, u8 *directory)
2338
u8 * GetSubDirectory(u8 *dirpath, u8 *directory)
2340
{
2339
{
2341
   u8 *cptr = dirpath;
2340
   u8 *cptr = dirpath;
2342
   u8 *dptr = directory;
2341
   u8 *dptr = directory;
2343
   u8 *retvalue = NULL;
2342
   u8 *retvalue = NULL;
2344
       
2343
       
2345
   /* if the first character of the path is an '/' we go to the next character */
2344
   /* if the first character of the path is an '/' we go to the next character */
2346
   if(*cptr == '/') cptr++;
2345
   if(*cptr == '/') cptr++;
2347
   /* search end of path or subdirectory*/
2346
   /* search end of path or subdirectory*/
2348
   while((*cptr != 0) && (*cptr != '/'))
2347
   while((*cptr != 0) && (*cptr != '/'))
2349
   {
2348
   {
2350
      *dptr = *cptr;
2349
      *dptr = *cptr;
2351
       dptr++;
2350
       dptr++;
2352
       cptr++;
2351
       cptr++;
2353
   }  
2352
   }  
2354
   if(*cptr!=0) retvalue = ++cptr;
2353
   if(*cptr!=0) retvalue = ++cptr;
2355
   *dptr = 0;
2354
   *dptr = 0;
2356
 
2355
 
2357
   return(retvalue);
2356
   return(retvalue);
2358
}
2357
}
2359
 
2358
 
2360
/********************************************************************************************************************************************/
2359
/********************************************************************************************************************************************/
2361
/*      Function:               s8 *GetPath(void);                                                                                                                                                                                                              */
2360
/*      Function:               s8 *GetPath(void);                                                                                                                                                                                                              */
2362
/*                                                                                                                                                                                                                                                                                      */
2361
/*                                                                                                                                                                                                                                                                                      */
2363
/*      Description:    This function function returns a pointer to the absolute path of the active partition                                                                   */
2362
/*      Description:    This function function returns a pointer to the absolute path of the active partition                                                                   */
2364
/*                                                                                                                                                                                                                                      */
2363
/*                                                                                                                                                                                                                                      */
2365
/*                                                                                                                                                                                                                                                                                      */
2364
/*                                                                                                                                                                                                                                                                                      */
2366
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2365
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2367
/********************************************************************************************************************************************/
2366
/********************************************************************************************************************************************/
2368
 
2367
 
2369
s8 *GetPath(void)
2368
s8 *GetPath(void)
2370
{
2369
{
2371
        return(Partition.PathToCwd);
2370
        return(Partition.PathToCwd);
2372
}
2371
}
2373
 
2372
 
2374
/********************************************************************************************************************************************/
2373
/********************************************************************************************************************************************/
2375
/*      Function:               void SetPathToRoot(void);                                                                                                                                                                                                       */
2374
/*      Function:               void SetPathToRoot(void);                                                                                                                                                                                                       */
2376
/*                                                                                                                                                                                                                                                                                      */
2375
/*                                                                                                                                                                                                                                                                                      */
2377
/*      Description:    This function sets the path to the rootdirectory                                                                                                                                                */
2376
/*      Description:    This function sets the path to the rootdirectory                                                                                                                                                */
2378
/*                                                                                                                                                                                                                                      */
2377
/*                                                                                                                                                                                                                                      */
2379
/*                                                                                                                                                                                                                                                                                      */
2378
/*                                                                                                                                                                                                                                                                                      */
2380
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2379
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2381
/********************************************************************************************************************************************/
2380
/********************************************************************************************************************************************/
2382
 
2381
 
2383
void SetPathToRoot(void)
2382
void SetPathToRoot(void)
2384
{
2383
{
2385
        /* lets point to the rootdirectory */
2384
        /* lets point to the rootdirectory */
2386
        strcpy(Partition.PathToCwd, "/");      
2385
        strcpy(Partition.PathToCwd, "/");      
2387
}
2386
}
2388
 
2387
 
2389
/********************************************************************************************************************************************/
2388
/********************************************************************************************************************************************/
2390
/*      Function:               void AppendDirToPath(s8* directory);                                                                                                                                                                                    */
2389
/*      Function:               void AppendDirToPath(s8* directory);                                                                                                                                                                                    */
2391
/*                                                                                                                                                                                                                                                                                      */
2390
/*                                                                                                                                                                                                                                                                                      */
2392
/*      Description:    This function function appends the name of an directory to the Path to the CWD                                                                                  */
2391
/*      Description:    This function function appends the name of an directory to the Path to the CWD                                                                                  */
2393
/*                                                                                                                                                                                                                                      */
2392
/*                                                                                                                                                                                                                                      */
2394
/*                                                                                                                                                                                                                                                                                      */
2393
/*                                                                                                                                                                                                                                                                                      */
2395
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2394
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2396
/********************************************************************************************************************************************/
2395
/********************************************************************************************************************************************/
2397
 
2396
 
2398
void AppendDirToPath(s8* directory)
2397
void AppendDirToPath(s8* directory)
2399
{
2398
{
2400
        /* append the name of the directory to the path */
2399
        /* append the name of the directory to the path */
2401
        strcat(Partition.PathToCwd, directory);
2400
        strcat(Partition.PathToCwd, directory);
2402
        /* append a '/' after the directoryname */
2401
        /* append a '/' after the directoryname */
2403
        strcat(Partition.PathToCwd, "/");
2402
        strcat(Partition.PathToCwd, "/");
2404
}
2403
}
2405
 
2404
 
2406
/********************************************************************************************************************************************/
2405
/********************************************************************************************************************************************/
2407
/*      Function:               RemoveLastDirFromPath(void);                                                                                                                                                                                    */
2406
/*      Function:               RemoveLastDirFromPath(void);                                                                                                                                                                                    */
2408
/*                                                                                                                                                                                                                                                                                      */
2407
/*                                                                                                                                                                                                                                                                                      */
2409
/*      Description:    This function removes the last directory from the path to the cwd                                                                                                               */
2408
/*      Description:    This function removes the last directory from the path to the cwd                                                                                                               */
2410
/*                                                                                                                                                                                                                                      */
2409
/*                                                                                                                                                                                                                                      */
2411
/*                                                                                                                                                                                                                                                                                      */
2410
/*                                                                                                                                                                                                                                                                                      */
2412
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2411
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2413
/********************************************************************************************************************************************/
2412
/********************************************************************************************************************************************/
2414
 
2413
 
2415
void RemoveLastDirFromPath(void)
2414
void RemoveLastDirFromPath(void)
2416
{
2415
{
2417
        /* a pointer to the beginning of the absolute path to the cwd */
2416
        /* a pointer to the beginning of the absolute path to the cwd */
2418
        s8 * cptr = Partition.PathToCwd;
2417
        s8 * cptr = Partition.PathToCwd;
2419
        /* lets find the end of the path to the cwd */
2418
        /* lets find the end of the path to the cwd */
2420
        while(*cptr != 0) cptr++;
2419
        while(*cptr != 0) cptr++;
2421
        /* if the path is terminated with an '/' */
2420
        /* if the path is terminated with an '/' */
2422
        if((*(cptr-1)) == '/') *(cptr-1)=0;    
2421
        if((*(cptr-1)) == '/') *(cptr-1)=0;    
2423
        /* now lets find the beginning of the last directorientry */
2422
        /* now lets find the beginning of the last directorientry */
2424
        while((*cptr != '/') && cptr > Partition.PathToCwd) cptr--;
2423
        while((*cptr != '/') && cptr > Partition.PathToCwd) cptr--;
2425
        /* is there one subdirectory left within the path? */
2424
        /* is there one subdirectory left within the path? */
2426
        if(cptr > Partition.PathToCwd)
2425
        if(cptr > Partition.PathToCwd)
2427
        {
2426
        {
2428
                /* we delete the direntry by terminating the path with 0 */
2427
                /* we delete the direntry by terminating the path with 0 */
2429
                *cptr = 0;
2428
                *cptr = 0;
2430
        }
2429
        }
2431
        /* there is no subdirectory left within the path. Therefore we create the root instead. */
2430
        /* there is no subdirectory left within the path. Therefore we create the root instead. */
2432
        else
2431
        else
2433
        {
2432
        {
2434
                *cptr = '/';
2433
                *cptr = '/';
2435
                *(cptr+1) = 0;
2434
                *(cptr+1) = 0;
2436
        }
2435
        }
2437
}
2436
}
2438
 
2437
 
2439
/********************************************************************************************************************************************/
2438
/********************************************************************************************************************************************/
2440
/*      Function:               chdir_(s8* filepath);                                                                                                                                                                                                   */
2439
/*      Function:               chdir_(s8* filepath);                                                                                                                                                                                                   */
2441
/*                                                                                                                                                                                                                                                                                      */
2440
/*                                                                                                                                                                                                                                                                                      */
2442
/*      Description:    This function changed the current working directory to the directory specified by the filepath                                                  */
2441
/*      Description:    This function changed the current working directory to the directory specified by the filepath                                                  */
2443
/*                  by function findfirst()                                                                                                                                                                                                     */
2442
/*                  by function findfirst()                                                                                                                                                                                                     */
2444
/*                                                                                                                                                                                                                                                                                      */
2443
/*                                                                                                                                                                                                                                                                                      */
2445
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2444
/*      Returnvalue:                                                                                                                                                                                                                                                    */
2446
/********************************************************************************************************************************************/
2445
/********************************************************************************************************************************************/
2447
/*                                                                         
2446
/*                                                                         
2448
#define ATTR_NONE               0x00    // normal file
2447
#define ATTR_NONE               0x00    // normal file
2449
#define ATTR_READONLY           0x01    // file is readonly
2448
#define ATTR_READONLY           0x01    // file is readonly
2450
#define ATTR_HIDDEN                     0x02    // file is hidden
2449
#define ATTR_HIDDEN                     0x02    // file is hidden
2451
#define ATTR_SYSTEM                     0x04    // file is a system file
2450
#define ATTR_SYSTEM                     0x04    // file is a system file
2452
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
2451
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
2453
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
2452
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
2454
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
2453
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
2455
#define ATTR_ARCHIVE            0x20    // file is new or modified
2454
#define ATTR_ARCHIVE            0x20    // file is new or modified
2456
*/
2455
*/
2457
 
2456
 
2458
u8 chdir_(s8 *path)
2457
u8 chdir_(s8 *path)
2459
{
2458
{
2460
        u8              retvalue = 0;                                   // the value returned by this function
2459
        u8              retvalue = 0;                                   // the value returned by this function
2461
        u32     ultemp = 0;                                             // temp. variable
2460
        u32     ultemp = 0;                                             // temp. variable
2462
        u8     *directory = path;                               // pointer to a directoryname within the path
2461
        u8     *directory = path;                               // pointer to a directoryname within the path
2463
        u8      dircount = 0;                                   // the number of subdirectoryentries within the path
2462
        u8      dircount = 0;                                   // the number of subdirectoryentries within the path
2464
        u8      cache[64];                                              // a buffer containing the name of the subdirectory we are actually looking for
2463
        u8      cache[64];                                              // a buffer containing the name of the subdirectory we are actually looking for
2465
        Find_t  fe;                                                             // The findelement needed for function findfirst to find the subdirectoryentry
2464
        Find_t  fe;                                                             // The findelement needed for function findfirst to find the subdirectoryentry
2466
        s8              tp[256];                                                // temporarily we remember the actual path until the operation has finished successfully
2465
        s8              tp[256];                                                // temporarily we remember the actual path until the operation has finished successfully
2467
        u32     cwdt = 0;
2466
        u32     cwdt = 0;
2468
        s8     *cptr;
2467
        s8     *cptr;
2469
 
2468
 
2470
        /* bring the path into the correct syntax */
2469
        /* bring the path into the correct syntax */
2471
        cptr = path;
2470
        cptr = path;
2472
        /* search the whole string */
2471
        /* search the whole string */
2473
        while(*cptr != 0)
2472
        while(*cptr != 0)
2474
        {
2473
        {
2475
                if(*cptr == '\\') *cptr = '/';
2474
                if(*cptr == '\\') *cptr = '/';
2476
                cptr++;
2475
                cptr++;
2477
        }
2476
        }
2478
        /* lets remember the actual path */
2477
        /* lets remember the actual path */
2479
        strcpy(tp, Partition.PathToCwd);
2478
        strcpy(tp, Partition.PathToCwd);
2480
        cwdt = Partition.CurrentWorkingDirectory;
2479
        cwdt = Partition.CurrentWorkingDirectory;
2481
        /* how many subdirectories are there within the path? */
2480
        /* how many subdirectories are there within the path? */
2482
        dircount = GetDirCount(path);  
2481
        dircount = GetDirCount(path);  
2483
        /* if the path is absolute we begin at the rootdirectory */
2482
        /* if the path is absolute we begin at the rootdirectory */
2484
        if(path[0] == '/')
2483
        if(path[0] == '/')
2485
        {
2484
        {
2486
                strcpy(Partition.PathToCwd, "/");
2485
                strcpy(Partition.PathToCwd, "/");
2487
                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2486
                Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
2488
                /* if there is no other pathinformation we only switch to the rootdirectory. So theres nothing left todo.*/
2487
                /* if there is no other pathinformation we only switch to the rootdirectory. So theres nothing left todo.*/
2489
                if(!dircount) return(1);
2488
                if(!dircount) return(1);
2490
        }
2489
        }
2491
        /* now we parse through all the subdirectories within the path */
2490
        /* now we parse through all the subdirectories within the path */
2492
        do
2491
        do
2493
        {  
2492
        {  
2494
                /* until all the subdirectories within the path have been processed */
2493
                /* until all the subdirectories within the path have been processed */
2495
        if(dircount) dircount--;
2494
        if(dircount) dircount--;
2496
                /* this is the name of the next subdirectory we are looking for */             
2495
                /* this is the name of the next subdirectory we are looking for */             
2497
            directory = GetSubDirectory(directory, cache);  
2496
            directory = GetSubDirectory(directory, cache);  
2498
                /* search for the next subdirectory within the path */
2497
                /* search for the next subdirectory within the path */
2499
                if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe))
2498
                if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe))
2500
                {
2499
                {
2501
                        /* we try to change into the directory "..". Now we have to delete the last direntry from the path */
2500
                        /* we try to change into the directory "..". Now we have to delete the last direntry from the path */
2502
                        if(strcmp(cache,"..") == 0) RemoveLastDirFromPath();
2501
                        if(strcmp(cache,"..") == 0) RemoveLastDirFromPath();
2503
                        /* we try to change into the actual directory so there's nothing todo */
2502
                        /* we try to change into the actual directory so there's nothing todo */
2504
                        else if(cache[0] == '.') return(1);
2503
                        else if(cache[0] == '.') return(1);
2505
                        /* otherwise we append the name of the directory we are changing in to the path */
2504
                        /* otherwise we append the name of the directory we are changing in to the path */
2506
                        else AppendDirToPath(cache);
2505
                        else AppendDirToPath(cache);
2507
                        /* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */
2506
                        /* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */
2508
                        ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
2507
                        ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
2509
                        /* the first 2 entries are reserved for '.' and '..' */
2508
                        /* the first 2 entries are reserved for '.' and '..' */
2510
                        ultemp -= 2;
2509
                        ultemp -= 2;
2511
                        /* now we have to transform the position within the fat into the corrosponding sectoraddress relative to the beginning of the datasection of the active partition*/
2510
                        /* 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*/
2512
                        ultemp *= Partition.SectorsPerCluster;
2511
                        ultemp *= Partition.SectorsPerCluster;
2513
                        /* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */
2512
                        /* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */
2514
                        ultemp += Partition.FirstDataSector;
2513
                        ultemp += Partition.FirstDataSector;
2515
                        /* the cwd now points to the specified directory */
2514
                        /* the cwd now points to the specified directory */
2516
                        Partition.CurrentWorkingDirectory = ultemp;
2515
                        Partition.CurrentWorkingDirectory = ultemp;
2517
                        /* we found the folder specified by the foldername */
2516
                        /* we found the folder specified by the foldername */
2518
                        retvalue = 1;
2517
                        retvalue = 1;
2519
                }
2518
                }
2520
        }
2519
        }
2521
        /* do this until all subdirectories have been found or a subdirectory is missing */
2520
        /* do this until all subdirectories have been found or a subdirectory is missing */
2522
        while(dircount && retvalue);
2521
        while(dircount && retvalue);
2523
 
2522
 
2524
        /* if we could not change to the specified directory we restore the actual path */
2523
        /* if we could not change to the specified directory we restore the actual path */
2525
        if(!retvalue)
2524
        if(!retvalue)
2526
        {
2525
        {
2527
                Partition.CurrentWorkingDirectory = cwdt;                                                  
2526
                Partition.CurrentWorkingDirectory = cwdt;                                                  
2528
                strcpy(Partition.PathToCwd, tp);
2527
                strcpy(Partition.PathToCwd, tp);
2529
        }
2528
        }
2530
        return(retvalue);      
2529
        return(retvalue);      
2531
}
2530
}
2532
 
2531