From 0f4456a3280420cde1814ca3afc73d44ac364da0 Mon Sep 17 00:00:00 2001 From: Pavel Vymetálek Date: Tue, 21 Jul 2015 22:43:19 +0200 Subject: Přidáno čtení (dump) ze sériového portu do tap souboru.\n\nPřidán progress bar pro čtení. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- taptoser.c | 321 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 203 insertions(+), 118 deletions(-) diff --git a/taptoser.c b/taptoser.c index 20b962e..1e0d4e0 100644 --- a/taptoser.c +++ b/taptoser.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #define false 0 @@ -18,24 +19,35 @@ // SERIAL char MODEMDEVICE[64]; -FILE *outfile = NULL; +FILE *tapout_fd = NULL; int is_outfile = 0; int baud_rate = 0; -#define FILENAME_LENGTH 2048 +#define FILENAME_LENGTH 400 char output_dump_file[FILENAME_LENGTH]; char tap_file[FILENAME_LENGTH]; +unsigned char in_buff[16386]; +unsigned char *p_buff; +unsigned int is_reading = 1; + static int inp_indx = 0; int serial_fd; size_t out_indx; +struct sigaction saterm; /* definition of signal action */ + + +// variables for progress bar +unsigned int pos_progress; float width, progress_pos, progress_part; +long pos = 0; void usage(void) { printf ("Tap file serial port uploader/downloader. (c)2012 Pavel Vymetálek \n"); - printf ("Usage:\ntaptoser [-v] [-h] [-o] [-b|--baud baud_rate] /dev/serial tap_file\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 (program and protocol)\n"); printf ("\t-h, --help\tShow this text\n"); + printf ("\t-d, --device\tCommunication device\n"); printf ("\t-b, --baud\tSet the communication speed. 9600Bd or 19200Bd are supported by ZX Spectrum\n"); printf ("\t-o, --outfile\tOutput to file, instead of stdout. Without coloring ESC sequences\n"); } @@ -56,9 +68,9 @@ void TestCts(void) { int status; do { ioctl(serial_fd, TIOCMGET, &status); - usleep (100); if (status & 0x20) break; -// printf ("status: %X\n",status); + usleep (100); + // printf ("status: %X\n",status); } while (1); } @@ -70,12 +82,13 @@ void TestArgs (int argc, char *argv[]) int option_index = 0; static struct option long_options[] = { {"outfile", required_argument, NULL, 'o'}, + {"device", required_argument, NULL, 'd'}, {"baud", required_argument, NULL, 'b'}, {"version", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; - c = getopt_long (argc, argv, "o:b:vh", long_options, &option_index); + c = getopt_long (argc, argv, "o:d:b:vh", long_options, &option_index); if (c == -1) // konec parametru break; @@ -88,8 +101,12 @@ void TestArgs (int argc, char *argv[]) case 'b': baud_rate = atoi(optarg); break; + case 'd': + strncpy(MODEMDEVICE, optarg, strlen(optarg)); +// printf ("Serial port: %s\n", MODEMDEVICE); + break; case 'o': - strncpy (&output_dump_file[0], optarg, FILENAME_LENGTH); + strncpy (output_dump_file, optarg, strlen(optarg)); is_outfile = 1; break; case 'v': @@ -104,7 +121,6 @@ void TestArgs (int argc, char *argv[]) /* Done with options. OPTIND points to first nonoption argument. */ if (optind < argc) { while (optind < argc){ - strncpy (&MODEMDEVICE[0], argv[optind++], 63); strncpy (&tap_file[0], argv[optind++], 63); } } @@ -130,11 +146,11 @@ void tooshort(FILE *fd) exit(2); } +// decode header void decode(unsigned char *header) { char name[11]; unsigned int n; - unsigned int pos_progress; strncpy(name, (char*)(header+2), 10); name[10] = '\0'; @@ -170,35 +186,189 @@ void decode(unsigned char *header) printf("\n"); } -int main(int argc, char** argv, char** env) -{ - FILE *fd; - unsigned int err, no, l; - long pos = 0; +void signal_handler_sigterm (int status) { + is_reading = 0; +// if (is_outfile) { +// fclose (tapout_fd); +// } +// printf ("\n\nbye...\n"); +// exit (0); +} + +int GetTerminalWidth(void) { + struct winsize termsize; + ioctl (STDOUT_FILENO, TIOCGWINSZ, &termsize); + return (termsize.ws_col); +} + +void DoProgress(size_t pos, size_t max) { + width = GetTerminalWidth(); + float percent, p, m; + int imax = width - 40; + int ipercent; + int px; + p = pos; + m = max; + percent = 100 / m * p; + ipercent = percent / 100 * imax; + +// printf ("\npercent: %f, ipercent: %d\n", percent, ipercent); + printf ("Received bytes: %6d/%6d [", (int) pos, (int)max); + for (px = 0; px < imax; px++) { + if (px < ipercent) printf ("="); + else printf (" "); + } + printf ("] %3d %%\r", (int)percent); + fflush (stdout); +} + +void RecvTap() { + unsigned int err, len; + size_t total_len = 0, last_len = 0; + tapout_fd = fopen (output_dump_file, "a"); + if (tapout_fd == NULL) { + err = errno; + error (1, err, "can't open output file"); + } +// if (is_outfile) { + printf("Output file is: %s\n", output_dump_file); +// } else { +// outfile = stdout; +// } + while (is_reading) { + usleep (100000); + len = read (serial_fd, in_buff, 256); + p_buff = in_buff; + total_len += len; + p_buff += len; + while (len) { + fputc(*p_buff, tapout_fd); + p_buff++; + len--; + if (total_len != last_len) { + last_len = total_len; + DoProgress(total_len, 16384); + } + } + } + fclose (tapout_fd); + + printf ("\n\nulozeno...\n"); +} + +void SendByte(unsigned char *p_dato) { + unsigned char dat; +// TestCts(); + // write byte to serial port + dat = *p_dato; + printf ("%2.2X ", dat); +// write (serial_fd, p_dato, 1); +// // tcdrain(serial_fd); + usleep (200); +} + +void SendTap() { + FILE *tap_fd; + unsigned int err, no, len; struct stat st; unsigned char header[19]; - struct winsize termsize; - ioctl (STDOUT_FILENO, TIOCGWINSZ, &termsize); - printf ("width: %d \n", termsize.ws_col); - width = termsize.ws_col; + 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) { + pos += no = fread(header, 1, 2, tap_fd); + if (no != 2) + tooshort(tap_fd); + for (out_indx = 0; out_indx < 2; out_indx++) { + progress_pos = 0; + printf("["); + 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 ("NO header: %d\n", no); + decode(header); + for (out_indx = 0; out_indx < 19; out_indx++) { + SendByte(&header[out_indx]); + usleep (3000); + } + usleep (10000); + } 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); + progress_part = h_len / width; + // for (progress_pos = 0; progress_pos < out_indx*progress_part; progress_pos++) { + // printf ("#\r"); + // } + + // usleep (1000); + if (no != 1) tooshort(tap_fd); + printf("Flag: %u\n\n", (int)*header); + len--; + } + else { + len = no; + } + pos += len; + // no = fseek(fd, pos, SEEK_SET); + // if (no != 0) + // { + // err = errno; + // error(1, err, "can't seek in input file"); + // } + printf ("NO datablock: %d\n\n", len); + for (out_indx = 0; out_indx < len; out_indx++) { + fread(header, 1, 1, tap_fd); + SendByte(header); + // printf ("len: %5d\r", out_indx); + // usleep (621); + } + printf ("\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(); struct termios oldtio, newtio; - int z; inp_indx = 0; if (argc < 3) { printf("You must specify the Serial device and file\n"); usage(); exit(1); } + printf ("tu som... \n"); TestArgs (argc, argv); + printf ("Serial device: %s, communication speed is: %d Bd\n", MODEMDEVICE, baud_rate); - if (is_outfile) { - outfile = fopen (output_dump_file, "a"); - printf("Output file is: %s\n", output_dump_file); - } else { - outfile = stdout; - } /* 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) { @@ -228,99 +398,14 @@ int main(int argc, char** argv, char** env) tcflush(serial_fd, TCIOFLUSH); tcsetattr(serial_fd, TCSANOW, &newtio); Set_DTR(true); - - no = stat(tap_file, &st); - if (no != 0) - { - err = errno; - error(1, err, "can't stat input file"); - } - - fd = fopen(tap_file, "r"); - if (fd == NULL) - { - err = errno; - error(1, err, "can't open input file"); - } - - while (pos < st.st_size) - { - - pos += no = fread(header, 1, 2, fd); - if (no != 2) - tooshort(fd); - for (out_indx = 0; out_indx < 2; out_indx++) { - TestCts(); - progress_pos = 0; - - printf("["); - write (serial_fd, &header[out_indx], 1); - usleep (200); - } - - no = getword(header); - if (no == 19) /* HEADER */ - { - pos += no = fread(header, 1, 19, fd); - if (no != 19) - tooshort(fd); - printf ("NO header: %d\n", no); - decode(header); - for (out_indx = 0; out_indx < 19; out_indx++) { - TestCts(); - write (serial_fd, &header[out_indx], 1); - usleep (3000); - } - usleep (10000); - - } else { - if (h_len != no - 2) /* zobrazuj iba bloky bez hl. */ - { - l = no; - printf ("NO datablock without header: %d\n", no); - printf("Type: datablock\nLength: %u\n", l - 2); - pos += no = fread(header, 1, 1, fd); - TestCts(); - write (serial_fd, header, 1); - progress_part = h_len / width; - -// for (progress_pos = 0; progress_pos < out_indx*progress_part; progress_pos++) { -// printf ("#\r"); -// } - - usleep (1000); - if (no != 1) - tooshort(fd); - printf("Flag: %u\n\n", (int)*header); - l--; - } - else - { - l = no; - } - - pos += l; - - - -// no = fseek(fd, pos, SEEK_SET); -// if (no != 0) -// { -// err = errno; -// error(1, err, "can't seek in input file"); -// } - printf ("NO datablock: %d\n\n", l); - for (out_indx = 0; out_indx < l; out_indx++) { - fread(header, 1, 1, fd); - TestCts(); - write (serial_fd, header, 1); -// printf ("len: %5d\r", out_indx); - usleep (621); - } - printf ("\n"); - } + + if (is_outfile) { + // cteni souboru ze seriaku + RecvTap(); + } else { + // poslat na seriak tap soubor + SendTap(); } - - fclose(fd); + close (serial_fd); return 0; } -- cgit