Subversion Repositories NaviCtrl

Rev

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

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