/*#######################################################################################*/
/* !!! 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
+10]; // rx & tx buffer to avoid 2 buffers
#define KEYWORD_COUNT 55
// most used gpx tags can be compressed
const char keyword
[KEYWORD_COUNT
][16]=
{"Altimeter>\0 \0",
"MotorCurrent>\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",
"0,0,0,0\0 \0",
"name>\0 \0",
"FCFlags2>\0 \0",
"MagnetField>\0 \0",
"trkseg>\0 \0",
"AnalogInputs>\0 \0",
"Servo>\0 \0",
"BL_State>\0 \0",
"BL_MaxPWM>\0 \0",
"MikroKopter\0 \0",
"nter>000</\0 \0",
"metadata>\0 \0",
"Speak>\0 \0",
"MotorNOK>\0 \0",
"Gas>\0 \0",
"ShutterCnt>\0 \0",
"ele_raw>\0 \0",
"GPSInfo>\0 \0",
"Gimbal>\0 \0",
"Laser>\0 \0",
"ExCtl>\0 \0",
"<WP>----,0,0,0<\0",
"MagnetInclinati\0",
"BL_Temperature>\0",
"AvaiableMotorPo\0",
"FC_I2C_ErrorCou\0",
"FC_SPI_ErrorCou\0",
"TargetDistance>\0"
};
//ACHTUNG: ggf. DATA_TRANSFER_SIZE vergrössern
u16 CompressBuffer
(char *buf
, u16 size
, u16 offset
)
{
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;
// any file or directory except volume labels and hidden files
if(findfirst_
("*.*", (ATTR_ARCHIVE
|ATTR_SUBDIRECTORY
|ATTR_SYSTEM
|ATTR_READONLY
), &fe
))
{
memcpy(&FTP_direntry.
Name, &fe.
name, 13);
FTP_direntry.
Attribute = fe.
fp.
Attribute;
FTP_direntry.
Size = fe.
fp.
Size;
}
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;
}
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &FTP_direntry
, sizeof(FTP_direntry
));
break;
case FTP_CMD_GET_CWD
: // get current working directory
{
char data_null
= 0;
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 3, &FTP_command
, 1, getcwd_
(), strlen(getcwd_
()), &data_null
, 1 );
}
break;
case FTP_CMD_SET_CWD
: // set current working directory
{
u8 cmd_successful
;
cmd_successful
= chdir_
(FTP_data
);
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &cmd_successful
, 1);
}
break;
case FTP_CMD_CDUP
: // change dir up
{
u8 cmd_successful
;
cmd_successful
= chdir_
("..");
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &cmd_successful
, 1);
}
break;
case FTP_CMD_MKDIR
: // create directory
{
u8 cmd_successful
;
cmd_successful
= mkdir_
(&FTP_data
[0]);
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &cmd_successful
, 1);
}
break;
case FTP_CMD_CHANGE_BAUDATE
: // change baudrate
{
u8 cmd_successful
;
u32 baudrate
;
baudrate
= FTP_data
[0];
baudrate
|= ((u32
)FTP_data
[1] * 0x100);
baudrate
*= 100;
UART1_Configure
(baudrate
);
UART1_BaudrateFallbackTimeout
= 700; // set global var to check UART communication in polling
cmd_successful
= 1;
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &cmd_successful
, 1);
}
break;
case FTP_CMD_PING
: // ping
{
u8 cmd_successful
= 1;
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &cmd_successful
, 1);
UART1_BaudrateFallbackTimeout
= 0;
}
break;
case FTP_CMD_RMDIR
: // delete directory
{
u8 cmd_successful
;
cmd_successful
= rmdir_
(&FTP_data
[0]);
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &cmd_successful
, 1);
}
break;
case FTP_CMD_DELETE_FILE
: // delete file
{
u8 cmd_successful
;
cmd_successful
= fdelete_
(&FTP_data
[0]);
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &cmd_successful
, 1);
}
break;
case FTP_CMD_OPEN_FILE
: // open the file for reading
{
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
{
u32 filepos
;
blockindex
= FTP_data
[0];
filepos
= FTP_data
[1];
filepos
|= ((u32
)FTP_data
[2] * 0x100);
filepos
|= ((u32
) FTP_data
[3] * 0x10000L
);
filepos
|= ((u32
) FTP_data
[4] * 0x1000000L
);
fseek_
(fp
, filepos
, SEEK_SET
); // set filepointer to beginning of requested block
}
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_CREATE_FILE
: // open the file for writing
{
u16 size
= DATA_TRANSFER_SIZE
;
//compressLevel = FTP_data[0];
// FTP_data[1..4] contains filesize in bytes
compressLevel
= 0; // no compression for writing
fp
= fopen_
(&FTP_data
[5], 'w');
if (fp
!= NULL
)
{
blockindex
= 0; // reset index counter
}
else size
= 0; // this means, no valid file for transfer (maybe readonly)
//if (size == 0) Debug("ftp: create ERR ");
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &size
, 2);
}
break;
case FTP_CMD_SEND_FILE_DATA
:
{
u16 size
= (u8
)FTP_data
[2];
size
*= 0x100;
size
+= (u8
) FTP_data
[1];
// if (FTP_data[0] == blockindex) // next block is requested
{
blockindex
++;
fwrite_
(&FTP_data
[3], size
, 1, fp
); // write data block to buffer);
}
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 2, &FTP_command
, 1, &blockindex
, 1 );
}
break;
case FTP_CMD_NONE
:
default:
FTP_command
= FTP_CMD_NONE
;
Debug
("ftp: CMD None");
break;
case FTP_CMD_GET_KEYWORDS
:
{
u8 count
= KEYWORD_COUNT
;
MKProtocol_CreateSerialFrame
(&UART1_tx_buffer
, 'F', NC_ADDRESS
, 3, &FTP_command
, 1, &count
, 1, keyword
, sizeof(keyword
) );
}
break;
}
}