Subversion Repositories NaviCtrl

Compare Revisions

Ignore whitespace Rev 348 → Rev 349

/trunk/fat16.c
55,6 → 55,7
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <stdio.h>
#include <string.h>
#include "91x_lib.h"
#include "timer1.h"
#include "fat16.h"
61,6 → 62,7
#include "sdc.h"
#include "uart1.h"
 
void Test(void);
//________________________________________________________________________________________________________________________________________
// Module name: fat16.c
// Compiler used: avr-gcc 3.4.5
126,6 → 128,8
u32 NoSectorsPartition ; // Number of Sectors in the Partition
} __attribute__((packed)) PartitionEntry_t;
 
 
 
/*
Coding of Cylinder/Sector words
 
309,10 → 313,12
u32 FirstRootDirSector; // sector of the rootdirectory
u32 FirstDataSector; // sector of the first cluster containing data (cluster2).
u32 LastDataSector; // the last data sector of the partition
u8 VolumeLabel[12]; // the volume label
} Partition_t;
u8 VolumeLabel[12]; // the volume label
u32 CurrentWorkingDirectory;// A pointer to the directory we are actual using
s8 PathToCwd[256]; // a string containing the complete path to the current working directory
} __attribute__((packed)) Partition_t;
 
Partition_t Partition; // Structure holds partition information
Partition_t Partition; // Structure holds partition information
 
File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used.
 
571,7 → 577,6
 
UART1_PutString("\r\n FAT16 init...");
Partition.IsValid = 0;
 
// declare the filepointers as unused.
for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
{
654,7 → 659,11
goto end;
}
Partition.IsValid = 1; // mark data in partition structure as valid
Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector;
strcpy(Partition.PathToCwd,"/");
result = 0;
 
// Test();
end:
if(result != 0) Fat16_Deinit();
else UART1_PutString("ok");
1037,7 → 1046,6
// dir entries can be searched only in filesclusters that have
// a corresponding dir entry with adir-flag set in its attribute
// or direct within the root directory area
 
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED;
// no current directory exist therefore assume searching in the root
if(file->DirectorySector == SECTOR_UNDEFINED)
1092,7 → 1100,7
 
do // loop over all data clusters of the current directory entry
{
dir_sector = 0; // reset sector counter within a new cluster
dir_sector = 0;
do // loop over all sectors of a cluster or all sectors of the root directory
{
curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number
1350,6 → 1358,14
path = (s8*)filename; // start a the beginning of the filename string
file->DirectorySector = 0; // start at RootDirectory with file search
file->DirectoryIndex = 0;
/* if a path begins with a '/' at index 0 the search starts at the rootdirectory otherwise we will start relative to the cwd */
if(path[0] != '/')
{
/* is the current working directory the rootdirectory? */
if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0;
/* otherwise we are working in an subdirectory */
else file->DirectorySector = Partition.CurrentWorkingDirectory;
}
// as long as the file was not found and the remaining path is not empty
while((*path != 0) && !file_exist)
{ // separate dirname and subpath from filepath string
1559,7 → 1575,7
{ // if it could not be created
fclose_(file);
file = NULL;
}
}
break;
case 'r': // else opened for 'r'
default: // if unsupported mode
1662,7 → 1678,7
 
if( (!Partition.IsValid) || (file == NULL)) return(c);
// if the end of the file is not reached, get the next character.
if((0 < file->Size) && ((file->Position+1) < file->Size) )
if((0 < file->Size) && ((file->Position) < file->Size) )
{
curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read.
curr_sector += file->SectorOfCurrCluster;
2041,3 → 2057,486
UnlockFilePointer(file);
return(pVolumeLabel);
}
 
 
 
#define ATTR_NONE 0x00 // normal file
#define ATTR_READONLY 0x01 // file is readonly
#define ATTR_HIDDEN 0x02 // file is hidden
#define ATTR_SYSTEM 0x04 // file is a system file
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name
#define ATTR_ARCHIVE 0x20 // file is new or modified
 
 
/********************************************************************************************************************************************/
/* Function: u8 FindItem(Find_t); */
/* */
/* Description: This function looks for the item specified by global structure FindElement in the actual directory */
/* */
/* */
/* Returnvalue: TRUE if an matching element was found */
/********************************************************************************************************************************************/
 
u8 FindItem(Find_t *findelement)
{
u16 index = 0;
u16 end_of_directory_not_reached = 1; // the directory has been read completely without a result.
u8 i = 0;
u8 readpointer = 0;
u8 writepointer = 0;
u8 retvalue = 0;
DirEntry_t *DirectoryEntry;
File_t file;
 
file.FirstSectorOfCurrCluster = findelement->fp.FirstSectorOfCurrCluster;
file.SectorOfCurrCluster = findelement->fp.SectorOfCurrCluster;
index = findelement->fp.DirectoryIndex;
 
 
do
{ // search the next 16 rootentries in this sector of the roordirectory.
SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache); // Read the Rootdirectory.
DirectoryEntry = (DirEntry_t *)file.Cache;
 
while((!retvalue)&&(index<16))
{
i=0;
if((u8) DirectoryEntry[index].Name[0] != 0xe5) // ignore deleted items.
{
while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?'))
{
i++;
}
}
if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11))
{
for(readpointer=0;readpointer<=10;readpointer++)
{
if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8))
{
findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure.
writepointer++;
}
else
{
if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE)
{
if(readpointer < 8) readpointer=8;
if(DirectoryEntry[index].Name[readpointer] != ' ')
{
findelement->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8.
writepointer++;
findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure.
writepointer++;
}
else break;
}
else break;
}
/* terminate the namestring with 0 for debugpurposes*/
findelement->name[12] = 0;
}
findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster;
findelement->fp.DirectoryIndex = index;
findelement->fp.FirstSectorOfCurrCluster = file.FirstSectorOfCurrCluster;
findelement->fp.DirectorySector = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster);
findelement->fp.SectorOfCurrCluster = file.SectorOfCurrCluster;
findelement->fp.Size = DirectoryEntry[index].Size;
findelement->fp.Attribute = DirectoryEntry[index].Attribute;
retvalue = 1;
}
index++;
}
if(!retvalue) // file not found in this sector so take next sector.
{
file.SectorOfCurrCluster++;
if(file.SectorOfCurrCluster >= Partition.SectorsPerCluster)
{
file.SectorOfCurrCluster=0;
end_of_directory_not_reached = GetNextCluster(&file);
}
}
index = 0;
}
while((end_of_directory_not_reached) && (!retvalue));
 
return(retvalue);
}
 
 
/********************************************************************************************************************************************/
/* Function: findnext_(Find_t *); */
/* */
/* Description: This function looks for the next item in the specified directory with a matching filename and fileattributes specified */
/* by function findfirst() */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
u8 findnext_(Find_t * findelement)
{
u8 itemfound = 0;
u8 index = 0;
 
findelement->fp.DirectoryIndex++;
 
/* before we start searching an element we clear the complete namestring within the structure FindElement */
for(index=0;index<11;index++) findelement->name[index] = 0;
 
if(FindItem(findelement))
{
itemfound = 1;
}
 
return(itemfound);
}
 
 
 
/********************************************************************************************************************************************/
/* Function: findfirst_(s8* filename, u8 attribfilter, u8 attribmask, Find_t *); */
/* */
/* Description: This function looks for the first item in the specified directory with a matching filename and fileattributes */
/* The filename of the element found is transformed from 8.3 to a string */
/* */
/* */
/* Returnvalue: (1) if Element was found. (0) if no valid element was found */
/********************************************************************************************************************************************/
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement)
{
u8 itemfound = 0;
u8 index = 0;
 
/* initialize the FindElement structure */
findelement->fp.FirstSectorOfFirstCluster = 0; // First sector of the first cluster of the file.
findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory; // First sector of the cluster which is edited at the moment.
findelement->fp.SectorOfCurrCluster = 0; // The sector within the current cluster.
findelement->fp.ByteOfCurrSector = 0; // The byte location within the current sector.
findelement->fp.Size = 0; // The size of the opend file in bytes.
findelement->fp.Position = 0; // Pointer to a character within the file 0 < fileposition < filesize
findelement->fp.DirectorySector = 0; // the sectorposition where the directoryentry has been made.
findelement->fp.DirectoryIndex = 0; // The index to the directoryentry within the specified sector.
findelement->attribfilter = 0;
findelement->attribmask = attribmask;
findelement->searchstring[0]=0;
 
/* seperate the name of the element to be found from the filepath and bring it to the 8.3*/
SeperateDirName(name, findelement->searchstring);
/* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */
for(index=0;index<8;index++)
{
/* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
if(findelement->searchstring[index] == '*')
{
/* */
while(++index <8) findelement->searchstring[index] = '*';
}
}
for(index=8;index<11;index++)
{
/* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */
if(findelement->searchstring[index] == '*')
{
/* */
while(++index <11) findelement->searchstring[index] = '*';
}
}
/* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */
findelement->fp.DirectoryIndex--;
/* now lets search for the item within the direcory */
itemfound = findnext_(findelement);
 
return(itemfound);
}
 
 
/********************************************************************************************************************************************/
/* Function: u8 GetDirCount(s8* filepath); */
/* */
/* Description: This function counts the number of subdirectories the dirpath contains */
/* */
/* */
/* Returnvalue: then number of subdirectories within the specified path */
/********************************************************************************************************************************************/
u8 GetDirCount(u8 *dirpath)
{
u8 i=0;
u8 cnt=0;
 
while(dirpath[i] != 0)
{
if(dirpath[i]=='/')
{
if(dirpath[i+1]!=0) cnt++; // ignore last'/'
}
i++;
}
i=0;
return(cnt);
}
 
 
/********************************************************************************************************************************************/
/* Funtion: char *GetSubDirectory (char *dirpath, char *directory) */
/* */
/* Description: this function returns a pointer to the beginning of the next subdirectory or NULL */
/* */
/* */
/* returnvalue: number of subdirectories in the filepath */
/********************************************************************************************************************************************/
u8 * GetSubDirectory(u8 *dirpath, u8 *directory)
{
u8 *cptr = dirpath;
u8 *dptr = directory;
u8 *retvalue = NULL;
/* if the first character of the path is an '/' we go to the next character */
if(*cptr == '/') cptr++;
/* search end of path or subdirectory*/
while((*cptr != 0) && (*cptr != '/'))
{
*dptr = *cptr;
dptr++;
cptr++;
}
if(*cptr!=0) retvalue = ++cptr;
*dptr = 0;
 
return(retvalue);
}
 
/********************************************************************************************************************************************/
/* Function: s8 *GetPath(void); */
/* */
/* Description: This function function returns a pointer to the absolute path of the active partition */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
s8 *GetPath(void)
{
return(Partition.PathToCwd);
}
 
/********************************************************************************************************************************************/
/* Function: void SetPathToRoot(void); */
/* */
/* Description: This function sets the path to the rootdirectory */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
void SetPathToRoot(void)
{
/* lets point to the rootdirectory */
strcpy(Partition.PathToCwd, "/");
}
 
/********************************************************************************************************************************************/
/* Function: void AppendDirToPath(s8* directory); */
/* */
/* Description: This function function appends the name of an directory to the Path to the CWD */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
void AppendDirToPath(s8* directory)
{
/* append the name of the directory to the path */
strcat(Partition.PathToCwd, directory);
/* append a '/' after the directoryname */
strcat(Partition.PathToCwd, "/");
}
 
/********************************************************************************************************************************************/
/* Function: RemoveLastDirFromPath(void); */
/* */
/* Description: This function removes the last directory from the path to the cwd */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
void RemoveLastDirFromPath(void)
{
/* a pointer to the beginning of the absolute path to the cwd */
s8 * cptr = Partition.PathToCwd;
/* lets find the end of the path to the cwd */
while(*cptr++ != 0);
/* now lets find the beginning of the last directorientry */
while(*cptr-- != '/');
/* we delete the direntry by terminating the path with 0 */
*++cptr = 0;
}
 
/********************************************************************************************************************************************/
/* Function: chdir_(s8* filepath); */
/* */
/* Description: This function changed the current working directory to the directory specified by the filepath */
/* by function findfirst() */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
/*
#define ATTR_NONE 0x00 // normal file
#define ATTR_READONLY 0x01 // file is readonly
#define ATTR_HIDDEN 0x02 // file is hidden
#define ATTR_SYSTEM 0x04 // file is a system file
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name
#define ATTR_ARCHIVE 0x20 // file is new or modified
*/
 
u8 chdir_(s8 *path)
{
u8 retvalue = 0; // the value returned by this function
u32 ultemp = 0; // temp. variable
u8 *directory = path; // pointer to a directoryname within the path
u8 dircount = 0; // the number of subdirectoryentries within the path
u8 cache[64]; // a buffer containing the name of the subdirectory we are actually looking for
Find_t fe; // The findelement needed for function findfirst to find the subdirectoryentry
s8 tp[256]; // temporarily we remember the actual path until the operation has finished successfully
u32 cwdt = 0;
 
/* lets remember the actual path */
strcpy(tp, Partition.PathToCwd);
cwdt = Partition.CurrentWorkingDirectory;
/* if the path is absolute we begin at the rootdirectory */
strcpy(Partition.PathToCwd, "/");
/* how many subdirectories are there within the path? */
dircount = GetDirCount(path);
/* now we parse through all the subdirectories within the path */
do
{
/* until all the subdirectories within the path have been processed */
if(dircount) dircount--;
/* this is the name of the next subdirectory we are looking for */
directory = GetSubDirectory(directory, cache);
/* search for the next subdirectory within the path */
if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe))
{
/* we try to change into the directory "..". Now we have to delete the last direntry from the path */
if(strcmp(cache,"..") == 0) RemoveLastDirFromPath();
/* we try to change into the actual directory so there's nothing todo */
else if(cache[0] == '.') return(1);
/* otherwise we append the name of the directory we are changing in to the path */
else AppendDirToPath(cache);
/* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */
ultemp = (u32) fe.fp.FirstSectorOfFirstCluster;
/* the first 2 entries are reserved for '.' and '..' */
ultemp -= 2;
/* 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*/
ultemp *= Partition.SectorsPerCluster;
/* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */
ultemp += Partition.FirstDataSector;
/* the cwd now points to the specified directory */
Partition.CurrentWorkingDirectory = ultemp;
/* we found the folder specified by the foldername */
retvalue = 1;
}
}
/* do this until all subdirectories have been found or a subdirectory is missing */
while(dircount && retvalue);
 
/* if we could not change to the specified directory we restore the actual path */
if(!retvalue)
{
Partition.CurrentWorkingDirectory = cwdt;
strcpy(Partition.PathToCwd, tp);
}
return(retvalue);
}
 
/********************************************************************************************************************************************/
/* Function: void Test(void); */
/* */
/* Description: Diese Funktion demonstriert die Möglichkeiten der Funktionen findfirst_() findnext_() und changedir_() */
/* */
/* */
/* Returnvalue: */
/********************************************************************************************************************************************/
 
void Test(void)
{
File_t *fp = NULL;
Find_t fe;
u32 cwd = 0;
 
 
cwd = Partition.CurrentWorkingDirectory;
sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text);
/* Als Erstes suchen wir uns das erste Unterverzeichnis (ATTR_SUBDIRECTORY) auf der Speicherkarte */
if(findfirst_("*.*", ATTR_SUBDIRECTORY, &fe))
{
/* Danach wechseln wir in in dieses Unterverzeichnis auf der speicherkarte */
if(chdir_(fe.name))
{
sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text);
/* Dann finden wir die erste Datei (ATTR_ARCIVE) in diesem Unterverzeichnis */
if(findfirst_("*.*", ATTR_ARCHIVE, &fe))
{
/* Der Name der gefundenen Datei wird ausgegeben */
UART1_PutString("\r\n");
UART1_PutString(fe.name);
/* nun wir die erste gefundene Datei im Unterverzeichnis lesend geöffnet */
fp = fopen_(fe.name, 'r');
if(fp != NULL){
/* und die erste Zeile aus dem Inhalt ausgegeben */
fgets_(text,60,fp);
UART1_PutString("\r\n");
UART1_PutString(text);
fclose_(fp);
}
else {
UART1_PutString("\r\nfile not found");
}
 
/* anschließend suchen wir alle weiteren Dateien im aktuellen Unterverzeichnis */
while(findnext_(&fe))
{
/* und geben ebenfalls deren Namen */
UART1_PutString("\r\n");
UART1_PutString(fe.name);
/* sowie nach dem Öffnen ihren Inhalt aus */
fp = fopen_(fe.name, 'r');
if(fp != NULL)
{
fgets_(text,60,fp);
UART1_PutString("\r\n");
UART1_PutString(text);
fclose_(fp);
}
}
}
}
}
Partition.CurrentWorkingDirectory = cwd;
sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text);
if(chdir_("/ordner1/ordner12/ordner13"))
{
sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text);
fp = fopen_("Datei13.txt", 'r');
if(fp != NULL){
/* und die erste Zeile aus dem Inhalt ausgegeben */
fgets_(text,60,fp);
UART1_PutString("\r\n");
UART1_PutString(text);
fclose_(fp);
}
else {
UART1_PutString("\r\nfile not found");
}
}
else
UART1_PutString("\r\ndirectory not found");
/* jetzt sind wir wieder im Rootverzeichnis */
Partition.CurrentWorkingDirectory = cwd;
sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text);
}
 
/trunk/fat16.h
38,7 → 38,35
u8 State; // State of the filepointer (used/unused/...)
} File_t;
 
#define ATTR_NONE 0x00 // normal file
#define ATTR_READONLY 0x01 // file is readonly
#define ATTR_HIDDEN 0x02 // file is hidden
#define ATTR_SYSTEM 0x04 // file is a system file
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name
#define ATTR_ARCHIVE 0x20 // file is new or modified
#define ATTR_ANY_FILE 0x3F // all files
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Structure of an item used by functions findfirst and findnext
//________________________________________________________________________________________________________________________________________
 
typedef struct
{
File_t fp; // filepointer used to get access to the filesystemstructure
s8 searchstring[11]; // findfirst and findnext will only return elements within the specified directory matching this searchstring.
s8 name[13]; // the name of the element found within the specified directory
u8 active; // if the attribute active is set the name and the attributes of an element found within DirectoryEntryExist will be entered into the structure
u8 attribfilter;
u8 attribmask;
} __attribute__((packed)) Find_t;
 
//________________________________________________________________________________________________________________________________________
//
// API to the FAT16 filesystem
//
61,9 → 89,14
s16 fputs_(s8 * const string, File_t * const file);
s8 * fgets_(s8 * const string, s16 length, File_t * const file);
u8 feof_(File_t * const file);
u8 findfirst_(const s8* name, u8 attribmask, Find_t *);
u8 findnext_(Find_t *);
u8 chdir_(s8 *folder);
s8 *GetPath(void);
 
 
 
 
#endif //_FAT16_H
 
 
/trunk/ftphelper.c
0,0 → 1,254
/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 2008 Ingo Busker, Holger Buss
// + Nur für den privaten Gebrauch / NON-COMMERCIAL USE ONLY
// + FOR NON COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
// + bzgl. der Nutzungsbedingungen aufzunehmen.
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
// + Verkauf von Luftbildaufnahmen, usw.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permitted
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * porting the sources to other systems or using the software on other systems (except hardware from www.mikrokopter.de) is not allowed
//
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "91x_lib.h"
#include "config.h"
#include "main.h"
#include "fat16.h"
#include "ftphelper.h"
#include "mkprotocol.h"
#include "debug.h"
#include "uart1.h"
 
 
typedef struct
{
u8 Name[13];
u8 Attribute;
u32 Size;
 
} __attribute__((packed)) FTP_direntry_t;
 
FTP_direntry_t FTP_direntry;
 
char FTP_data[DATA_TRANSFER_SIZE+1]; // rx & tx buffer to avoid 2 buffers
 
u16 CompressBuffer(char *buf, u16 size, u16 offset)
{
#define KEYWORD_COUNT 27
 
const char keyword[KEYWORD_COUNT][16]=
{"Altimeter>\0 \0",
"Current>\0 \0",
"Variometer>\0 \0",
"GroundSpeed>\0 \0",
"VerticalSpeed>\0\0",
"FlightTime>\0 \0",
"Voltage>\0 \0",
"Capacity>\0 \0",
"RCQuality>\0 \0",
"RCRSSI>\0 \0",
"Compass>\0 \0",
"NickAngle>\0 \0",
"RollAngle>\0 \0",
"NCFlag>\0 \0",
"ErrorCode>\0 \0",
"TargetBearing>\0\0",
"RCSticks>\0 \0",
"GPSSticks>\0 \0",
"extensions>\0 \0",
"Course>\0 \0",
"trkpt\0 \0",
"time>\0 \0",
"sat>\0 \0",
"ele>\0 \0",
" lat=\0 \0",
" lon=\0 \0",
"TargetDistance>\0" };
u16 i, count = size;
char *s = NULL, *start = buf+offset;
 
for ( i = 0; i < KEYWORD_COUNT; i++)
{
s = strstr(start, keyword[i]);
if (s != NULL)
{ u8 keylen = strlen(keyword[i]);
*s= 27;
*(s+1) = i+1;
count-= (keylen-2);
memcpy(s+2, s+keylen, count - (s-buf));
i--;
}
}
return (count);
}
// --------------------------------------------------------------------
void CheckFTPCommand(u8 FTP_command)
{
static Find_t fe;
static File_t *fp = NULL;
static u8 blockindex, compressLevel = 0;
u32 filesize;
 
switch (FTP_command)
{
case FTP_CMD_FINDFIRST:
FTP_direntry.Name[0] = 0;
if (findfirst_("*.*", 0x35, &fe))
{
memcpy(&FTP_direntry.Name, &fe.name, 13);
FTP_direntry.Attribute = fe.fp.Attribute;
FTP_direntry.Size = fe.fp.Size;
// Debug(FTP_direntry.Name);
}
MKProtocol_CreateSerialFrame(&UART1_tx_buffer, 'F', NC_ADDRESS, 2, &FTP_command, 1, &FTP_direntry, sizeof(FTP_direntry));
break;
case FTP_CMD_FINDNEXT:
FTP_direntry.Name[0] = 0;
 
if (findnext_(&fe))
{
memcpy(&FTP_direntry.Name, &fe.name, 13);
FTP_direntry.Attribute = fe.fp.Attribute;
FTP_direntry.Size = fe.fp.Size;
// Debug(FTP_direntry.Name);
}
MKProtocol_CreateSerialFrame(&UART1_tx_buffer, 'F', NC_ADDRESS, 2, &FTP_command, 1, &FTP_direntry, sizeof(FTP_direntry));
break;
case FTP_CMD_GET_CWD:
{
char data_null = 0;
MKProtocol_CreateSerialFrame(&UART1_tx_buffer, 'F', NC_ADDRESS, 3, &FTP_command, 1, GetPath(), strlen(GetPath()), &data_null, 1 );
}
break;
case FTP_CMD_SET_CWD:
chdir_(FTP_data);
break;
case FTP_CMD_OPEN_FILE:
{
u8 filefound;
compressLevel = FTP_data[0];
fp = fopen_(&FTP_data[1], 'r');
if (fp != NULL)
{
filefound = 1;
filesize = fp->Size;
blockindex = 0; // reset index counter
}
else filefound = 0; // this means, no valid file found for transfer
 
 
MKProtocol_CreateSerialFrame(&UART1_tx_buffer, 'F', NC_ADDRESS, 3, &FTP_command, 1, &filefound, 1, &filesize, sizeof(filesize));
}
break;
case FTP_CMD_GET_FILE_DATA:
{
u16 size = DATA_TRANSFER_SIZE;
if (FTP_data[0] == blockindex + 1) // next block is requested
{
blockindex++;
}
else if (FTP_data[0] == blockindex) // repeat last block
{
fseek_(fp, SEEK_CUR, -DATA_TRANSFER_SIZE); // set filepointer to beginning of last block
}
else blockindex = FTP_data[0]+ 10; // ABORT transfer, blockindex now out of valid range
fread_(FTP_data, DATA_TRANSFER_SIZE, 1, fp); // read data block to buffer);
FTP_data[DATA_TRANSFER_SIZE] = 0;
if (compressLevel)
{
size = CompressBuffer(FTP_data, DATA_TRANSFER_SIZE, 0);
if (compressLevel > 1)
{
if (size < DATA_TRANSFER_SIZE - 50)
{
fread_(&FTP_data[size], DATA_TRANSFER_SIZE - size, 1, fp); // read data block to buffer);
FTP_data[DATA_TRANSFER_SIZE] = 0;
size = CompressBuffer(FTP_data, DATA_TRANSFER_SIZE, size);
}
}
}
MKProtocol_CreateSerialFrame(&UART1_tx_buffer, 'F', NC_ADDRESS, 4, &FTP_command, 1, &blockindex, 1, &size, 2, &FTP_data, size);
}
break;
 
case FTP_CMD_CLOSE_FILE:
fclose_(fp);
Debug("ftp: CloseFile");
 
break;
 
case FTP_CMD_NONE:
default:
FTP_command = FTP_CMD_NONE;
Debug("ftp: CMD None");
break;
}
}
 
 
/trunk/ftphelper.h
0,0 → 1,20
#ifndef _FTPHELPER_H
#define _FTPHELPER_H
 
#define FTP_CMD_NONE 0
#define FTP_CMD_FINDFIRST 1
#define FTP_CMD_FINDNEXT 2
#define FTP_CMD_GET_CWD 3
#define FTP_CMD_SET_CWD 4
#define FTP_CMD_OPEN_FILE 5
#define FTP_CMD_GET_FILE_DATA 6
#define FTP_CMD_CLOSE_FILE 7
 
#define DATA_TRANSFER_SIZE 750 // size of 1 data block for filetransfer
 
char FTP_data[DATA_TRANSFER_SIZE+1]; // parameter from FTP_CMD_SET_CWD
 
extern void CheckFTPCommand(u8 FTP_command);
 
#endif
/trunk/main.h
9,7 → 9,7
#endif
 
//-----------------------
//#define DEBUG 0
#define DEBUG 0
//-----------------------
 
#define VERSION_MAJOR 0
/trunk/mkprotocol.c
68,7 → 68,7
va_list ap;
 
u8 a,b,c;
u8 ptr = 0;
u16 ptr = 0;
u16 tmpCRC = 0, i;
 
u8* pdata = NULL;
/trunk/uart1.c
76,6 → 76,7
#include "params.h"
#include "fifo.h"
#include "debug.h"
#include "ftphelper.h"
 
#define FALSE 0
#define TRUE 1
100,7 → 101,9
u8 UART1_DisplayKeys = 0;
u8 UART1_DisplayLine = 0;
u8 UART1_ConfirmFrame = 0;
u8 UART1_Request_FTP = FALSE;
 
 
UART_TypeDef *DebugUART = UART1;
 
#ifdef FOLLOW_ME
120,7 → 123,7
Buffer_t UART1_rx_buffer;
 
// the tx buffer
#define UART1_TX_BUFFER_LEN 150
#define UART1_TX_BUFFER_LEN 1024
u8 UART1_tbuffer[UART1_TX_BUFFER_LEN];
Buffer_t UART1_tx_buffer;
 
395,6 → 398,14
case NC_ADDRESS: // own Slave Address
switch(SerialMsg.CmdID)
{
case 'f': // ftp command
UART1_Request_FTP = SerialMsg.pData[0];
 
//if (UART1_Request_FTP == FTP_CMD_SET_CWD || UART1_Request_FTP == FTP_CMD_GET_FILE)
memcpy(&FTP_data, &SerialMsg.pData[1], sizeof(FTP_data)); // copy ftp parameter
break;
 
case 'z': // connection checker
memcpy(&Echo, SerialMsg.pData, sizeof(Echo)); // copy echo pattern
UART1_Request_Echo = TRUE;
668,6 → 679,11
Echo = 0; // reset echo value
UART1_Request_Echo = FALSE;
}
else if(UART1_Request_FTP && (UART1_tx_buffer.Locked == FALSE))
{
CheckFTPCommand(UART1_Request_FTP);
UART1_Request_FTP = FALSE;
}
else if((UART1_Request_WritePoint!= 0xFF) && (UART1_tx_buffer.Locked == FALSE))
{
MKProtocol_CreateSerialFrame(&UART1_tx_buffer, 'W', NC_ADDRESS, 1, &UART1_Request_WritePoint, sizeof(UART1_Request_WritePoint));
/trunk/uart1.h
131,6 → 131,7
 
extern UART_TypeDef *DebugUART;
extern volatile u8 SerialLinkOkay;
extern Buffer_t UART1_tx_buffer;
 
 
void UART1_Init(void);