#include <windows.h>
#include <stdio.h>
#include "blockio.h"
static bool IsCommand(int cmd) {
return(cmd>='A' && cmd<='Z'); // commands are uppercase characters
}
int SerialReceiveFile(HANDLE fh,char* fileName,char* block,DWORD restartat){
int err=TimedSendChar(RQ_READY,5000);
if (err) return err_send;
uint32_t fileSize=0,fileRead=restartat;
uint32_t datareceived;
uint32_t blockoffset=0;
uint8_t sequencenr=0;
uint8_t expectedsequencenr=0;
FILETIME fileDate={0,0};
for(;;) {
int retries=0; // Receive a whole block
do {
err=ReceiveNextBlock(block+blockoffset,maxblocksizeusb-blockoffset,&datareceived,&sequencenr);
if (IsCommand(err)) { // upload was aborted, this is already a new command!
TimedSendChar(RQ_CRCERR,5000); // requests re-send
return CMD_CRCERR; // wrong block received!
}
if (err==CMD_BODY && expectedsequencenr!=sequencenr)
err=CMD_CRCERR; // wrong block received!
if (err==CMD_CRCERR) {
printf("CRC-Error");
ClearBuffers(PURGE_RXCLEAR);
TimedSendChar(RQ_CRCERR,5000);
}
if (err==CMD_TIMEOUT) {
printf("Timeout!");
Sleep(1000);
ClearBuffers(PURGE_RXCLEAR);
TimedSendChar(RQ_CRCERR,500);
Sleep(2000);
}
} while ((err==CMD_CRCERR || err==CMD_TIMEOUT) && retries++<10);
if (err==CMD_ABORT || err==CMD_RECVERR || err==CMD_CRCERR || err==CMD_TIMEOUT)
return err;
if (err==CMD_BODY) expectedsequencenr++;
if (err==CMD_EOF) {
if (blockoffset>0) {
DWORD written;
if (!WriteFile(fh,block,blockoffset,&written,NULL)) return err_file;
fileRead += blockoffset;
}
if (fileDate.dwHighDateTime||fileDate.dwLowDateTime)
SetFileTime(fh,NULL,NULL,&fileDate);
TimedSendChar(RQ_OK,5000);
break;
}
if (err==CMD_SIZE) { // size block
char*pdate=strchr(block,'\t');
if (pdate) {
*pdate=0;
ConvertIsoDateToDateTime(++pdate,fileDate);
}
fileSize = atoi(block); // Send acknowledge for block
err = TimedSendChar(RQ_OK,5000);
}else if (err==CMD_BODY) { // body
uint32_t writesize; // Send acknowledge for block
err = TimedSendChar(RQ_OK,5000);
// Write to file if there is any data to write
writesize=datareceived;
if (fh!=INVALID_HANDLE_VALUE) {
// If less than 16k received, just increase block offset
// but only if blockoffset+2*DataReceived<maxblocksize
if (writesize<16384 && blockoffset+2*writesize<maxblocksizeusb) blockoffset+=writesize;
else {
DWORD written;
if (!WriteFile(fh,block,blockoffset+writesize,&written,NULL)) return err_file;
blockoffset=0;
}
fileRead += writesize;
}
}
}
return 0;
}
int SerialSendFile(HANDLE fh,char* filename,char* block,DWORD resumeat, BOOL sizeonly) {
uint32_t filesize;
uint8_t sequencenr;
FILETIME ft;
int err;
char bytereceived;
HANDLE searchhandle=0;
WIN32_FIND_DATA srec;
if (fh!=INVALID_HANDLE_VALUE) filesize=GetFileSize(fh,NULL);
else{
char dirbuf[MAX_PATH];
filesize=0xFFFFFFFF;
strncpy(dirbuf,filename+1,sizeof dirbuf-3);
char*p=dirbuf+strlen(dirbuf);
if (p[-1]=='\\') --p; // avoid double backslash (not good searching "c:\\*")
strcpy(p,"\\*"); // find any file
searchhandle=FindFirstFile(dirbuf,&srec);
}
sequencenr=0;
// Wait for RQ_READY
err=TimedReceiveChar(&bytereceived,5000);
if (err) { // timeout!
printf("Initial byte timeout!");
if (searchhandle!=INVALID_HANDLE_VALUE) FindClose(searchhandle);
return err;
}
if (bytereceived!=RQ_READY) {
printf("Initial byte receive error!");
if (searchhandle!=INVALID_HANDLE_VALUE) FindClose(searchhandle);
return err_recv;
}
// send header block
sprintf(block,"%d",filesize);
// send also date, separated by a Tab
if (GetFileTime(fh,NULL,NULL,&ft)) {
char *p=block+strlen(block);
strcpy(p,"\t");
if (!CreateIsoDateString(ft,p+1)) p[0]=0; //yyyymmddhhmmss
// don't send tab in case of error
err=SendNextBlockRetry10(CMD_SIZE,block,strlen(block)+1,0);
if (err!=RQ_OK) {
printf("Size block not acknowledged!");
if (searchhandle!=INVALID_HANDLE_VALUE) FindClose(searchhandle);
if (err==RQ_LOCALABORT) return err_abort;
return err_recv;
}
if (sizeonly) {
if (searchhandle!=INVALID_HANDLE_VALUE) FindClose(searchhandle);
return 0;
}
}
// send body
DWORD offset = resumeat;
while (offset < filesize) {
int blocksize=filesize-offset;
if (blocksize>maxblocksize) blocksize=maxblocksize;
if (filename[0]=='\\' && filename[1]==0) { // drives!
block[0]=0;
char* pNextName=block;
char drvbuf[8];
char ch;
for (ch='A';ch<='Z';ch++) {
strcpy(drvbuf,"a:\\");
drvbuf[0]=ch;
int tp=GetDriveType(drvbuf);
if (tp!=DRIVE_UNKNOWN && tp!=DRIVE_NO_ROOT_DIR) {
strcpy(pNextName,drvbuf);
strcat(pNextName,"\r\n");
pNextName+=strlen(pNextName);
}
}
blocksize=pNextName-(char*)block; // without #0 at end!
offset=filesize;
}else if (fh==INVALID_HANDLE_VALUE) { // directory!
block[0]=0;
blocksize=0;
char* pEndBody;
char* pNextName=block;
blocksize=1024; //maxblocksize;
pEndBody=block+blocksize-262; // if more files, continue in next block
while (searchhandle!=INVALID_HANDLE_VALUE && pNextName<pEndBody) {
if (strcmp(srec.cFileName,".") && strcmp(srec.cFileName,"..")) {
if (srec.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
pNextName+=sprintf(pNextName,"%s\\\t0\t",srec.cFileName);
}else{
pNextName+=sprintf(pNextName,"%s\t%d\t",srec.cFileName,srec.nFileSizeLow);
}
pNextName+=CreateIsoDateString(srec.ftLastWriteTime,pNextName);
pNextName+=sprintf(pNextName,"\t%d\r\n",srec.dwFileAttributes);
}
if (!FindNextFile(searchhandle,&srec)) {
FindClose(searchhandle);
searchhandle=INVALID_HANDLE_VALUE;
}
blocksize=pNextName-(char*)block; // without #0 at end!
}
if (searchhandle==INVALID_HANDLE_VALUE) offset=filesize;
}else if (blocksize>0) {
DWORD numBytesRead;
if (!ReadFile(fh,block,blocksize,&numBytesRead,NULL)) {
printf("ReadFile failed!");
return err_recv;
}
}
err=SendNextBlockRetry10(CMD_BODY,block,blocksize,sequencenr);
if (err!=RQ_OK) {
printf("Body block not acknowledged!");
if (searchhandle!=INVALID_HANDLE_VALUE) FindClose(searchhandle);
if (err==RQ_LOCALABORT) return err_abort;
return err_recv;
}
sequencenr++;
if (filesize!=0xFFFFFFFF) {
offset += blocksize;
}
}
if (searchhandle!=INVALID_HANDLE_VALUE) FindClose(searchhandle);
// Send end of file block
err=SendNextBlockRetry10(CMD_EOF,NULL,0,0);
if (err!=RQ_OK) { // timeout!
printf("End of file block not acknowledged!");
if (err==RQ_LOCALABORT) return err_abort;
return err_recv;
}
return err_ok;
}
int SerialSendChar(char byte) {
return TimedSendChar(byte,5000);
}
/********* utils.cpp ***************/
static int atoi1(const char*s) {return *s-'0';}
static int atoi2(const char*s) {return atoi1(s)*10+atoi1(s+1);}
static int atoi4(const char*s) {return atoi2(s)*100+atoi2(s+2);}
bool ConvertIsoDateToDateTime(const char*s,FILETIME&ft) {
SYSTEMTIME st;
st.wYear=atoi4(s);
st.wMonth=atoi2(s+4);
st.wDay=atoi2(s+6);
st.wHour=atoi2(s+8);
st.wMinute=atoi2(s+10);
st.wSecond=atoi2(s+12);
st.wDayOfWeek=0;
st.wMilliseconds=0;
FILETIME ft2;
if (!SystemTimeToFileTime(&st,&ft2)) {
ft.dwHighDateTime=0xFFFFFFFF;
ft.dwLowDateTime=0xFFFFFFFF;
return false;
}
return !!LocalFileTimeToFileTime(&ft2,&ft); // Totalcmd expects system time!
}
static void itoa2(char*s,int v) { // <v> must be <= 99
s[0]=v/10+'0';
s[1]=v%10+'0';
}
static void itoa4(char*s,int v) { // <v> must be <=9999
itoa2(s,v/100);
itoa2(s+2,v%100);
}
bool CreateIsoDateString(const FILETIME&ft,char*s) {
FILETIME ft2;
FileTimeToLocalFileTime(&ft,&ft2); // Totalcmd expects system time!
SYSTEMTIME datetime;
if (FileTimeToSystemTime(&ft2,&datetime)) {
itoa4(s,datetime.wYear);
itoa2(s+4,datetime.wMonth);
itoa2(s+6,datetime.wDay);
itoa2(s+8,datetime.wHour);
itoa2(s+10,datetime.wMinute);
itoa2(s+12,datetime.wSecond);
s[14]=0;
return true;
}
*s=0;
return false;
}
WORD Crc16CalcBlock(char*p,int len,WORD crc16) {
static WORD crctable[256]={
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
if (len) do{
crc16 = crc16<<8 ^ crctable[BYTE(HIBYTE(crc16)^*p++)];
}while(--len);
return crc16;
}
Detected encoding: ASCII (7 bit) | 2
|