aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Vymetálek <pavel@vym.cz>2019-02-07 17:05:56 +0100
committerPavel Vymetálek <pavel@vym.cz>2019-02-07 17:05:56 +0100
commitaee21c54320a5e85153314e8f4efdb7bea67e762 (patch)
tree0d717b1336035249a216203ef99271cf82728b8c
downloadsercp-pc-aee21c54320a5e85153314e8f4efdb7bea67e762.tar.gz
První commit: vychází se z programu taptoser
-rw-r--r--Makefile8
-rw-r--r--sercp.c786
2 files changed, 794 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ffe0501
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+PROJECT=sercp
+all:
+ gcc $(PROJECT).c -o $(PROJECT) -Wall -pedantic -MP -MD -std=gnu11 -Werror=format-security -O2
+debug:
+ gcc $(PROJECT).c -o $(PROJECT) -Wall -pedantic -MP -MD -std=gnu11 -Werror=format-security -g -O0
+
+clean:
+ rm -f $(PROJECT) $(PROJECT).d $(PROJECT).o
diff --git a/sercp.c b/sercp.c
new file mode 100644
index 0000000..05d2a14
--- /dev/null
+++ b/sercp.c
@@ -0,0 +1,786 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <termios.h>
+#include <error.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/signal.h>
+#include <fcntl.h>
+#include <poll.h>
+
+#define false 0
+#define FALSE 0
+#define true 1
+#define TRUE 1
+
+
+// SERIAL
+char MODEMDEVICE[64];
+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];
+unsigned char in_buff[65538];
+unsigned char *p_buff;
+unsigned int is_continue = 1;
+unsigned int is_binary = 0;
+struct pollfd spolfd_serial[1]; // pole descriptoru pro poll
+
+static int inp_indx = 0;
+int serial_fd;
+size_t out_indx;
+struct sigaction saterm; /* definition of signal action */
+
+float width; // width of terminal
+long pos = 0;
+int scp = 0;
+int is_scp_read = 0;
+
+typedef struct {
+ uint16_t block_len;
+ uint8_t block_xor;
+ uint8_t block_sum;
+} __attribute__((packed)) fi_sum;
+
+typedef struct {
+ uint16_t length; // delka dat ve fileinfo
+ uint8_t h_xor; // xor bajtu fileinfa od fi_numblocks
+ uint8_t h_sum; // sum bajtu fileinfa od fi_numblocks
+ uint8_t fi_numblocks; // pocet bloku
+ uint8_t fi_name[64]; // jmeno souboru - prozatim musi byt ve fromatu 8.3 - kvuli esxdosu
+ uint8_t fi_date[8]; // nepouzito
+ uint8_t fi_time[8]; // nepouzito
+ fi_sum fi_blocks[256]; // delky a soucty bloku
+} __attribute__((packed)) FILEINFO;
+
+FILEINFO fileinfo;
+
+
+void usage(void) {
+ printf ("Tap file over serial port uploader/downloader. (c)2012-2015 Pavel Vymetálek <pavel@vym.cz>\n");
+ printf ("Based on utility tapheader: http://zeroteam.sk/tapheader.html (c)2012 Michal Jurica <mike@zeroteam.sk>\n");
+ printf ("Usage:\ntaptoser [-v] [-h] [-o filename.tap] [-b|--baud baud_rate] -d /dev/serial tap_file\n");
+ printf ("\t-v, --version\tShow version info\n");
+ printf ("\t-h, --help\tShow this text\n");
+ printf ("\t-d, --device\tCommunication device\n");
+ printf ("\t-w, --wait\tWaiting in microseconds between transmitted bytes. Default is -w 200us\n");
+ 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) {
+ int status;
+ ioctl(serial_fd, TIOCMGET, &status);
+ if (level) {
+ status |= TIOCM_DTR;
+ } else {
+ status &= ~TIOCM_DTR;
+ }
+ ioctl(serial_fd, TIOCMSET, &status);
+}
+
+void TestCts(void) {
+ int status;
+ do {
+ ioctl(serial_fd, TIOCMGET, &status);
+ if (status & 0x20) break;
+ usleep (100);
+ if (is_continue == 0) return;
+ // printf ("status: %X\n",status);
+ } while (1);
+}
+
+
+void TestArgs (int argc, char *argv[])
+{
+ int c;
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"outfile", required_argument, NULL, 'o'},
+ {"device", required_argument, NULL, 'd'},
+ {"baud", required_argument, NULL, 'b'},
+ {"wait", required_argument, NULL, 'w'},
+ {"scp", no_argument, NULL, 's'},
+ {"read", no_argument, NULL, 'r'},
+ {"binary", no_argument, NULL, 'B'},
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {0, 0, 0, 0}
+ };
+ c = getopt_long (argc, argv, "o:d:b:w:srBvh", long_options, &option_index);
+ if (c == -1) {
+ // konec parametru
+ break;
+ }
+ switch (c) {
+ case 'h':
+ usage();
+ exit(1);
+ break;
+ case 'b':
+ baud_rate = atoi(optarg);
+ break;
+ case 'w':
+ wait_us = atoi(optarg);
+ wait_ms = atoi(optarg);
+ break;
+ case 's':
+ printf ("Serial CP mode is activated\n");
+ scp = 1;
+ break;
+ case 'r':
+ printf ("scp read...\n");
+ is_scp_read = 1;
+ break;
+ case 'd':
+ strncpy(MODEMDEVICE, optarg, strlen(optarg));
+// printf ("Serial port: %s\n", MODEMDEVICE);
+ break;
+ case 'o':
+ strncpy (output_dump_file, optarg, strlen(optarg));
+ is_outfile = 1;
+ break;
+ case 'B':
+ printf ("Running in binary output mode\n");
+ is_binary = 1;
+ break;
+ case 'v':
+ printf ("Version 0.9.1 2015-07-22\n");
+ exit(1);
+ break;
+ default:
+ break;
+ }
+ }
+ if (optind < argc) {
+ while (optind < argc){
+ strncpy (&tap_file[0], argv[optind++], 63); // input tap file name - without option switch
+ }
+ }
+}
+
+
+// from tapheader utility
+unsigned int h_len;
+
+unsigned int getword(unsigned char* data) {
+ return *data + 256 * (*(data + 1));
+}
+
+void tooshort(FILE *fd) {
+ printf("Input file too short.\n\n");
+ fclose(fd);
+ exit(2);
+}
+
+// decode header1
+void decode(unsigned char *header) {
+ char name[11];
+ unsigned int n;
+ printf("\n");
+ strncpy(name, (char*)(header+2), 10);
+ name[10] = '\0';
+ printf("Filename: %12s \n", name);
+ printf("Flag: %4u ", (unsigned int)*header);
+ n = getword(header+14);
+ h_len = getword(header+12);
+
+ switch(*(header+1)) {
+ case '\0':
+ printf("Type: 0 => program\nProgram length: %6u bytes ", h_len);
+ if (n < 32768) printf("Runs from line %5u\t", n);
+ printf("Length without variables: %5u bytes ", getword(header+16));
+ break;
+ case '\1':
+ printf("Type: 1 => number array\tLength: %6u bytes", h_len);
+ break;
+ case '\2':
+ printf("Type: 2 => character array\tLength: %6u bytes", h_len);
+ break;
+ case '\3':
+ if (n == 16384 && h_len == 6912)
+ printf("Type: 3 => screen image\n");
+ else
+ printf("Type: 3 => bytes "
+ "Start address: %5u\t"
+ "Length: %6u bytes\t3rd param: %4u",
+ n, h_len, getword(header+16));
+ break;
+ }
+ printf("\n");
+}
+
+void signal_handler_sigterm (int status) {
+ // CTRL+C pressed
+ is_continue = 0; // do not continue
+}
+
+int GetTerminalWidth(void) {
+ struct winsize termsize;
+ ioctl (STDOUT_FILENO, TIOCGWINSZ, &termsize);
+ return (termsize.ws_col);
+}
+
+#define PROGRESS_PERCENT 0
+#define PROGRESS_COMPLETTE 1
+#define PROGRESS_ERROR_CSUM 2
+
+void DoProgress(size_t pos, size_t max, unsigned char csum_ok) {
+ width = GetTerminalWidth();
+ float percent, p, m;
+ int imax = width - 40;
+ int ipercent;
+ int px;
+ char progress_char;
+ p = pos;
+ m = max;
+ percent = 100 / m * p;
+ ipercent = percent / 100 * imax;
+ if (is_binary) progress_char = '#';
+ else progress_char = '=';
+ printf ("Proceed bytes: %6d/%6d [", (int) pos, (int)max);
+ for (px = 0; px < imax; px++) {
+ if (px < ipercent) printf ("%c", progress_char);
+ else printf (" ");
+ }
+ if (csum_ok == 0) {
+ printf ("] %3d %%\r", (int)percent);
+ } else if (csum_ok == 1) {
+ printf ("] OK \r");
+ } else {
+ printf ("] ERR \r");
+ }
+ fflush (stdout);
+}
+
+#define HEADER_RAW_LEN 21
+
+void RecvTap() {
+ unsigned int err;
+ size_t len;
+ int result;
+ size_t block_pos = 0, last_block_pos = 0;
+ size_t block_len = 10000;
+ size_t tap_pos = 0;
+ unsigned char xor_csum, xor_csum_ok;
+ unsigned char *p_write;
+ unsigned char block_type; // typ bloku 255 data 0 - hlavicka
+ unsigned char recv_status = 0; // 0 - zacatek, 1 - hlavicka nactena, 2 - blok se nacita, 3- header less
+ tapout_fd = fopen (output_dump_file, "a");
+ if (tapout_fd == NULL) {
+ err = errno;
+ error (1, err, "can't open output file");
+ }
+ printf("Output file is: %s\n", output_dump_file);
+ p_buff = in_buff;
+ p_write = in_buff;
+ while (is_continue) {
+ result = poll (spolfd_serial, 1, 200); // 200ms timeout
+ if (result == 0) {
+ // nic neprislo
+ continue;
+ }
+ if (spolfd_serial[0].revents & POLLIN) {
+ len = read (serial_fd, p_buff, 256);
+ block_pos += len;
+ p_buff += len;
+ if (is_binary == 0) {
+ // ulozeni dat ze seriaku jako tap file
+ while (len) {
+ fputc(*p_write, tapout_fd);
+ p_write++;
+ len--;
+ }
+ }
+ if (block_pos != last_block_pos && recv_status >= 2) {
+ last_block_pos = block_pos;
+ DoProgress(block_pos, block_len+2, PROGRESS_PERCENT);
+ }
+ if (block_pos >= HEADER_RAW_LEN && recv_status == 0) {
+ recv_status = 1; // hlavicka nactena
+ block_len = getword(in_buff);
+ block_type = *(in_buff + 2);
+ if (block_type == 0) {
+ // Hlavicka komplet
+ decode (in_buff + 2);
+ block_len = 0;
+ block_pos = 0;
+ xor_csum = 0;
+ recv_status = 0;
+ p_buff = in_buff;
+ p_write = in_buff;
+ } else if (block_type == 255) {
+ // data block
+ printf ("Data block len: %6zu\n", block_len-2);
+ recv_status = 3;
+ }
+ continue;
+ }
+ if (block_pos > HEADER_RAW_LEN + 3 && recv_status == 1) {
+ // nactena delka dalsiho bloku
+ recv_status = 2;
+ block_len = getword(in_buff + HEADER_RAW_LEN);
+ block_type = *(in_buff + HEADER_RAW_LEN + 2);
+ printf ("Block len: %zu Block type: %d\n", block_len, block_type);
+ continue;
+ }
+ if (block_len + 2 == block_pos && recv_status > 2) {
+ // Blok komplet nacten cekej novy
+ block_len = getword(in_buff);
+ block_type = *(in_buff + 2);
+ for (tap_pos = 0; tap_pos < block_len -1; tap_pos++) {
+ xor_csum ^= *(in_buff + 2 + tap_pos);
+ }
+ xor_csum_ok = *(in_buff + 2 + block_len - 1);
+ if (xor_csum == xor_csum_ok) {
+ DoProgress(block_pos, block_len+2, PROGRESS_COMPLETTE); // vypis jeste OK
+ if (is_binary == 1) {
+ // binarni vystup do souboru
+ for (tap_pos = 0; tap_pos < block_len - 2; tap_pos++){
+ fputc(*(in_buff + 3 + tap_pos), tapout_fd); // uloz do souboru
+ }
+ DoProgress(tap_pos, block_len - 2, PROGRESS_COMPLETTE);
+ }
+// printf ("Checksum OK\n");
+ } else {
+ DoProgress(block_pos, block_len+2, PROGRESS_ERROR_CSUM); // vypis error CSUM
+ }
+ block_len = 0;
+ block_pos = 0;
+ xor_csum = 0;
+ recv_status = 0;
+ p_buff = in_buff;
+ p_write = in_buff;
+ continue;
+ }
+ }
+ }
+ fclose (tapout_fd);
+ printf ("\n\nulozeno...\n");
+}
+
+void SendByte(unsigned char *p_dato) {
+ TestCts();
+ write (serial_fd, p_dato, 1);
+// tcdrain(serial_fd); // better solution, but usleep at the next line is
+ usleep (wait_us); // faster solution, TODO change sleep time according to serial communication speed 200us is for 57600Bd
+}
+
+void SendTap() {
+ FILE *tap_fd;
+ unsigned int err, no, len;
+ struct stat st;
+ unsigned char header[19];
+
+ 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");
+ }
+ while (pos < st.st_size) {
+ if (is_continue == 0) break;
+ pos += no = fread(header, 1, 2, tap_fd);
+ if (no != 2)
+ tooshort(tap_fd);
+ for (out_indx = 0; out_indx < 2; out_indx++) {
+ SendByte(&header[out_indx]);
+ }
+ no = getword(header);
+ if (no == 19) /* HEADER */
+ {
+ pos += no = fread(header, 1, 19, tap_fd);
+ if (no != 19)
+ tooshort(tap_fd);
+// printf ("Header len: %d\n", no);
+ decode(header);
+ for (out_indx = 0; out_indx < 19; out_indx++) {
+ SendByte(&header[out_indx]);
+ }
+ } else {
+ if (h_len != no - 2) { /* zobrazuj iba bloky bez hl. */
+ len = no;
+ printf ("NO datablock without header: %d\n", no);
+ printf("Type: datablock\nLength: %u\n", len - 2);
+ pos += no = fread(header, 1, 1, tap_fd);
+ SendByte(header);
+ DoProgress(1, no, PROGRESS_PERCENT);
+ if (no != 1) tooshort(tap_fd);
+ printf("Flag: %u\n\n", (int)*header);
+ len--;
+ } else {
+ len = no;
+ }
+ pos += len;
+ for (out_indx = 0; out_indx < len; out_indx++) {
+ fread(header, 1, 1, tap_fd);
+ SendByte(header);
+ DoProgress(out_indx+1, len, PROGRESS_PERCENT);
+ if (is_continue == 0) break;
+ }
+ printf ("\n");
+ usleep (800000);
+ }
+ }
+ fclose(tap_fd);
+}
+
+
+int CheckFileInfo(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++;
+ }
+ if (fi_xor == p_fi->h_xor && fi_sum == p_fi->h_sum) {
+ return 0;
+ }
+ 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;
+ uint8_t b_sum = 0;
+ uint8_t block_xor;
+ uint8_t block_sum;
+ block_len = p_fi->fi_blocks[block_indx].block_len;
+ block_sum = p_fi->fi_blocks[block_indx].block_sum;
+ block_xor = p_fi->fi_blocks[block_indx].block_xor;
+ for (uint16_t indx = 0; indx < block_len; indx++) {
+ b_xor ^= *p_buffer;
+ b_sum += *p_buffer;
+ p_buffer++;
+ }
+ if (b_xor == block_xor && b_sum == block_sum) {
+ return 0; // vrat se, je to v poradku
+ }
+ 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) {
+ uint32_t overall_len = 0;
+ uint8_t block_num = p_fi->fi_numblocks;
+ for (uint8_t indx = 0; indx < block_num; indx++) {
+ overall_len += p_fi->fi_blocks[indx].block_len;
+ }
+ return overall_len;
+}
+
+void RecvSCP(void) {
+ int recv_phase = 0; // 0 - fileinfo, 1 - blok 16kiB, 2 - posledni blok
+ uint8_t block_index = 0;
+ int result;
+ uint16_t len;
+ uint16_t length = 0;
+ uint16_t expected_len = 0;
+// uint8_t expected_xor;
+// uint8_t expected_sum;
+ uint32_t overall_length = 0; // celkova delka souboru
+ uint32_t recv_length = 0; // zatim prijatych dat ze souboru
+ int err;
+
+ FILEINFO *p_fileinfo = &fileinfo;
+ unsigned char *p_buff = buff;
+ tapout_fd = NULL;
+
+ memset (p_fileinfo, 0, sizeof(fileinfo));
+ while (is_continue) {
+ result = poll (spolfd_serial, 1, 200); // 200ms timeout
+ if (result == 0) {
+ // nic neprislo
+ continue;
+ }
+ switch (recv_phase) {
+ case 0:
+ // prijem fileinfo
+ if (spolfd_serial[0].revents & POLLIN) {
+ len = read (serial_fd, p_buff, sizeof(fileinfo));
+ p_buff += len;
+ length += len;
+ if (length == sizeof(fileinfo)) {
+ memcpy((unsigned char*) p_fileinfo, buff, sizeof(fileinfo));
+ if (CheckFileInfo(p_fileinfo) == 0) {
+ printf("Prijato fileinfo\n");
+ overall_length = GetOverallLen(p_fileinfo);
+ printf("Nazev souboru: \"%s\" pocet bloku:%d, delka souboru: %u\n", p_fileinfo->fi_name, p_fileinfo->fi_numblocks, overall_length);
+ recv_phase++; // priste se uz prijimaji bloky
+ block_index = 0; // zacina se prvnim blokem
+ p_buff = buff; // buffer na zacatek
+ length = 0;
+ expected_len = p_fileinfo->fi_blocks[block_index].block_len;
+
+
+ tapout_fd = fopen ((char*)p_fileinfo->fi_name, "w");
+ if (tapout_fd == NULL) {
+ err = errno;
+ error (1, err, "can't open output file");
+ }
+// expected_xor = p_fileinfo->fi_blocks[block_index].block_xor;
+// expected_sum = p_fileinfo->fi_blocks[block_index].block_sum;
+ } else {
+ printf("Fileinfo neni v cajku. Koncim...\n");
+ break;
+ }
+ break;
+ } else if (length > sizeof(fileinfo)){
+ len = read (serial_fd, p_buff, sizeof(fileinfo));
+ printf("Nejaky bordel. Koncim...\n");
+ break;
+ }
+ }
+ break;
+ case 1:
+ // prijem datoveho bloku - max. delka 16kiB
+ if (spolfd_serial[0].revents & POLLIN) {
+ len = read (serial_fd, p_buff, expected_len);
+ p_buff += len;
+ expected_len -= len;
+ length += len;
+ recv_length += len;
+ DoProgress(recv_length, overall_length, PROGRESS_PERCENT);
+ if (length == p_fileinfo->fi_blocks[block_index].block_len) {
+ // prijaty prvni block
+// printf("Prijaty blok c.%d delky: %d\n", block_index, length);
+ if (CheckSumBlock(p_fileinfo, block_index, buff) == 0) {
+ // blok je v cajku - zapsat do souboru
+ if (tapout_fd) fwrite(buff, length, 1, tapout_fd);
+ }
+ length = 0;
+ p_buff = buff;
+ block_index++;
+ expected_len = p_fileinfo->fi_blocks[block_index].block_len;
+ }
+ if (expected_len == 0 || block_index == 255) {
+ printf ("\nKonec prenosu\n");
+ recv_phase++;
+ is_continue = 0;
+ break;
+ }
+ } else if (length > 16384) {
+ len = read (serial_fd, p_buff, 16384);
+ printf("Nejaky bordel. Koncim...\n");
+ break;
+ }
+ }
+ }
+ if (tapout_fd) fclose (tapout_fd);
+ printf ("\n\nulozeno...\n");
+}
+
+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)
+{
+ // osetreni breaku ^C
+ saterm.sa_handler = signal_handler_sigterm;
+ saterm.sa_flags = 0;
+ sigaction (SIGINT, &saterm, NULL);
+ width = GetTerminalWidth();
+
+ // nastaveni serioveho portu
+ struct termios oldtio, newtio;
+ inp_indx = 0;
+ if (argc < 3) {
+ printf("You must specify the Serial device and file\n");
+ usage();
+ exit(1);
+ }
+ TestArgs (argc, argv);
+ /* open the device to be non-blocking (read will return immediatly) */
+ serial_fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+ if (serial_fd < 0) {
+ perror(MODEMDEVICE);
+ return(-1);
+ }
+ tcgetattr(serial_fd, &oldtio); /* save current port settings */
+ switch (baud_rate){
+ default:
+ baud_rate = 57600; // default speed
+ newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | CSTOPB;// | CRTSCTS;
+ break;
+ case 115200:
+ newtio.c_cflag = B115200 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
+ case 57600:
+ 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, ale tady ne
+ break;
+ case 19200:
+ newtio.c_cflag = B19200 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
+ case 9600:
+ newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
+ case 4800:
+ newtio.c_cflag = B4800 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
+ case 2400:
+ newtio.c_cflag = B2400 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
+ case 1200:
+ newtio.c_cflag = B1200 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS;
+ break;
+ }
+ newtio.c_cflag |= CRTSCTS;
+ 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_oflag = 0;
+// newtio.c_oflag &= ~OPOST;
+ newtio.c_lflag = 0; //NOFLSH;
+ newtio.c_cc[VMIN] = 0;
+ newtio.c_cc[VTIME] = 10;
+ tcsetattr(serial_fd, TCSANOW, &newtio);
+ tcflush(serial_fd, TCIOFLUSH);
+ spolfd_serial[0].fd = serial_fd; // nastaveni hlidaneho descriptoru
+ spolfd_serial[0].events = POLLIN; // hlidaji se data na vstupu
+
+ if (scp) {
+ // serial copy activated
+ if (is_scp_read) {
+ RecvSCP();
+ } else {
+ SendSCP();
+ }
+ } else {
+ Set_DTR(true); // PC can read data from speccy everytime
+ if (is_outfile) {
+ RecvTap(); // cteni tap souboru ze seriaku a zapis na disk pocitace
+ } else {
+ SendTap(); // poslat na seriak tap soubor do spectra
+ }
+ }
+ close (serial_fd);
+ return 0;
+}