From a6ddb2c4314ff0647630a611b3d4d22c88c7c7f5 Mon Sep 17 00:00:00 2001 From: Pavel Vymetálek Date: Wed, 9 Jan 2019 16:59:07 +0100 Subject: Přidáno vysílání scp - včetně vytvoření fileinfo tabulky MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - default mezera mezi bloky je 800ms --- taptoser.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 2 deletions(-) diff --git a/taptoser.c b/taptoser.c index 87c9f15..bf6e061 100644 --- a/taptoser.c +++ b/taptoser.c @@ -25,6 +25,7 @@ FILE *tapout_fd = NULL; int is_outfile = 0; int baud_rate = 0; int wait_us = 200; +int wait_ms = 800; #define FILENAME_LENGTH 400 char output_dump_file[FILENAME_LENGTH]; char tap_file[FILENAME_LENGTH]; @@ -75,6 +76,10 @@ void usage(void) { printf ("\t-b, --baud\tSet the communication speed. 4800Bd, 9600Bd, 19200Bd and 57600Bd (default) are supported\n"); printf ("\t-B, --binary\tBinary output - received tap from ZX Spectrum will save without all tap's specific mishmash\n"); printf ("\t-o, --outfile\tOutput file. Usualy *.tap or *.bin with in --binary mode\n"); + printf ("SCP mode -----\n"); + printf ("\t-s, --scp\tSCP mode - sent files with fileinfo 1109bytes\n"); + printf ("\t-r, --read\tread file\n"); + printf ("\t-w, --wait\tWaiting in milliseconds between transmitted blocks. Default is -w 800 milliseconds\n"); } void Set_DTR(unsigned short level) { @@ -132,6 +137,7 @@ void TestArgs (int argc, char *argv[]) break; case 'w': wait_us = atoi(optarg); + wait_ms = atoi(optarg); break; case 's': printf ("Serial CP mode is activated\n"); @@ -458,6 +464,22 @@ int CheckFileInfo(FILEINFO* p_fi) { return -1; } +void CountFileInfoChecksum(FILEINFO* p_fi) { + unsigned char *p_fiinfo = (unsigned char*)p_fi; + uint16_t fi_len; + uint8_t fi_xor = 0; + uint8_t fi_sum = 0; + fi_len = p_fi->length; + p_fiinfo += 4; // suma se bude pocitat od offsetu 4 + for (uint16_t indx = 0; indx < (fi_len-4); indx++) { + fi_xor ^= *p_fiinfo; + fi_sum += *p_fiinfo; + p_fiinfo++; + } + p_fi->h_xor = fi_xor; + p_fi->h_sum = fi_sum; +} + int CheckSumBlock(FILEINFO* p_fi, uint8_t block_indx, uint8_t *p_buffer) { uint16_t block_len; uint8_t b_xor = 0; @@ -478,6 +500,20 @@ int CheckSumBlock(FILEINFO* p_fi, uint8_t block_indx, uint8_t *p_buffer) { return -1; // vrat se s chybou bloku } +void CountSumBlock(FILEINFO* p_fi, uint8_t block_indx, uint8_t *p_buffer, uint16_t block_len) { + uint8_t block_xor = 0; + uint8_t block_sum = 0; + for (uint16_t indx = 0; indx < block_len; indx++) { + block_xor ^= *p_buffer; + block_sum += *p_buffer; + p_buffer++; + } + p_fi->fi_blocks[block_indx].block_len = block_len; + p_fi->fi_blocks[block_indx].block_sum = block_sum; + p_fi->fi_blocks[block_indx].block_xor = block_xor; +} + + unsigned char buff[32768]; uint32_t GetOverallLen(FILEINFO *p_fi) { @@ -591,7 +627,75 @@ void RecvSCP(void) { } void SendSCP(void) { + FILE *tap_fd; + unsigned int err, no, len; + struct stat st; + FILEINFO *p_fileinfo = &fileinfo; + unsigned char *p_buff = buff; + uint32_t file_len; + uint8_t num_blocks = 0; + ssize_t odeslano; + uint32_t len_sent; + uint16_t sent_size; + uint32_t overall_sent; + + + no = stat(tap_file, &st); + if (no != 0) { + err = errno; + error(1, err, "can't stat input file"); + } + tap_fd = fopen(tap_file, "r"); + if (tap_fd == NULL) { + err = errno; + error(1, err, "can't open input file"); + } + printf ("Soubor %s delky: %ld\n", tap_file, st.st_size); + memset (p_fileinfo, 0, sizeof(fileinfo)); // smazat fileinfo + + memcpy(p_fileinfo->fi_name, tap_file, strlen(tap_file)); + file_len = (uint32_t) st.st_size; + while (file_len) { + len = fread(buff, 1, 16384, tap_fd); // precti 16kiB dat + CountSumBlock(p_fileinfo, num_blocks, buff, len); +// printf ("Blok c. %d, delka: %d\n", num_blocks, len); + file_len -= len; + num_blocks++; + } + p_fileinfo->fi_numblocks = num_blocks; + p_fileinfo->length = num_blocks*4 + 85; + CountFileInfoChecksum(p_fileinfo); + odeslano = write (serial_fd, (void*)p_fileinfo, sizeof(fileinfo)); + tcdrain(serial_fd); + printf("Fileinfo sent...\n"); + // TODO Cekat pauzu mezi bloky + usleep (wait_ms * 1000); + + rewind(tap_fd); // prenaseny soubor na zacatek + file_len = (uint32_t) st.st_size; + overall_sent = 0; + while (file_len && is_continue) { + len = fread(buff, 1, 16384, tap_fd); // precti 16kiB dat + p_buff = buff; + sent_size = 256; + len_sent = len; + while (len_sent && is_continue) { + odeslano = write (serial_fd, (void*)p_buff, sent_size); + tcdrain(serial_fd); + p_buff += odeslano; + overall_sent += odeslano; + len_sent -= odeslano; + if (len_sent < 256) { + sent_size = len_sent; + } + DoProgress(overall_sent, st.st_size, PROGRESS_PERCENT); + } + usleep (wait_ms * 1000); + file_len -= len; + } + printf("\nFile sent...\n"); + fclose(tap_fd); } int main(int argc, char** argv, char** env) @@ -630,7 +734,7 @@ int main(int argc, char** argv, char** env) newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; break; case 38400: - newtio.c_cflag = B38400 | CS8 | CLOCAL | CREAD | CRTSCTS; // dva stopbity jsou nastaveny vsude + newtio.c_cflag = B38400 | CS8 | CLOCAL | CREAD;// | CRTSCTS; // dva stopbity jsou nastaveny vsude break; case 19200: newtio.c_cflag = B19200 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; @@ -650,7 +754,7 @@ int main(int argc, char** argv, char** env) } printf ("Serial device: %s, communication speed is: %d Bd\n", MODEMDEVICE, baud_rate); // newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // vypne XON/XOFF - newtio.c_iflag = 0;IGNPAR | IXOFF; + newtio.c_iflag = 0; //IGNPAR | IXOFF; newtio.c_oflag = 0; // newtio.c_oflag &= ~OPOST; newtio.c_lflag = 0; //NOFLSH; -- cgit