diff options
| author | Pavel Vymetálek <pavel@vym.cz> | 2019-02-18 14:42:14 +0100 | 
|---|---|---|
| committer | Pavel Vymetálek <pavel@vym.cz> | 2019-02-18 14:42:14 +0100 | 
| commit | fb473ed61d28c2de73bcb729168ad9427fc4c631 (patch) | |
| tree | c352beaa709d8038330189f3f2186e431ce302c9 | |
| parent | 6943723b68d75c9b30fa08dea6cd4474b0af6316 (diff) | |
| download | sercp-pc-fb473ed61d28c2de73bcb729168ad9427fc4c631.tar.gz | |
Priprava pro prijem s pridanou cestou (path)
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | sercp.c | 379 | 
2 files changed, 64 insertions, 322 deletions
| @@ -1,7 +1,10 @@  PROJECT=sercp -all: +all:	$(PROJECT) + +sercp:	$(PROJECT).c  	gcc $(PROJECT).c -o $(PROJECT) -Wall -pedantic -MP -MD -std=gnu11 -Werror=format-security -O2 -debug: + +debug:	$(PROJECT).c  	gcc $(PROJECT).c -o $(PROJECT) -Wall -pedantic -MP -MD -std=gnu11 -Werror=format-security -g -O0  clean: @@ -4,6 +4,7 @@  #include <string.h>  #include <errno.h>  #include <stdint.h> +#include <libgen.h>  #include <getopt.h>  #include <termios.h>  #include <error.h> @@ -18,7 +19,7 @@  #define true 1  #define TRUE 1 - +const char* _version = "v0.2";  // SERIAL  char MODEMDEVICE[64];  FILE *tapout_fd = NULL; @@ -26,10 +27,9 @@ 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]; +char *path; +char tap_file[FILENAME_MAX]; +unsigned char buff[32768];  unsigned char *p_buff;  unsigned int is_continue = 1;  unsigned int is_binary = 0; @@ -64,69 +64,44 @@ typedef struct {  FILEINFO fileinfo; -  void usage(void) { -	printf ("sercp v0.2 (c)2018-2019 Pavel Vymetálek <pavel@vym.cz>\n"); +	printf ("sercp %s (c)2018-2019 Pavel Vymetálek <pavel@vym.cz>\n", _version);  	printf ("serial copy for transfering file to/from ZX Spectrum 128 AY's RS232\n");  	printf ("Uses 1109bytes of fileinfo - blocks sums, filename, etc.\n"); -	printf ("Usage:\nsercp -d /dev/serial [-v] [-h] [-b baud_rate] [-w time] [-r] <filename>\n"); +	printf ("Usage:\nsercp [-v] [-h] -d /dev/serial [-b baud_rate] [-w time] [-r] <filename>\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-b, --baud\tSet the communication speed. Default 38400Bd\n");  	printf ("\t-w, --wait\tWaiting in milliseconds between transmitted blocks. Default is -w 800 milliseconds\n"); -	printf ("\t-r, --read\tRead file from other computer (ZX Spectrum)\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); +	printf ("\t-r, --read\tRead file from serial port\n");  } -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); -} - - +// fileinfo 1109bytes +/************************************************************************/  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); +		c = getopt_long (argc, argv, "d:b:w:rvh", long_options, &option_index);  		if (c == -1) {  			// konec parametru  			break;  		}  		switch (c) { -			case 'h': -				usage(); -				exit(1); +			case 'd': +				strncpy(MODEMDEVICE, optarg, strlen(optarg)); +				// 				printf ("Serial port: %s\n", MODEMDEVICE);  				break;  			case 'b':  				baud_rate = atoi(optarg); @@ -135,28 +110,15 @@ void TestArgs (int argc, char *argv[])  				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"); +				printf ("%s\n", _version); +				exit(1); +				break; +			case 'h': +				usage();  				exit(1);  				break;  			default: @@ -171,61 +133,14 @@ void TestArgs (int argc, char *argv[])  } -// 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); @@ -236,6 +151,7 @@ int GetTerminalWidth(void) {  #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; @@ -264,183 +180,7 @@ void DoProgress(size_t pos, size_t max, unsigned char csum_ok) {  	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; @@ -460,6 +200,7 @@ int CheckFileInfo(FILEINFO* p_fi) {  	return -1;  } +/************************************************************************/  void CountFileInfoChecksum(FILEINFO* p_fi) {  	unsigned char *p_fiinfo = (unsigned char*)p_fi;  	uint16_t fi_len; @@ -476,6 +217,7 @@ void CountFileInfoChecksum(FILEINFO* p_fi) {  	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; @@ -496,6 +238,7 @@ 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; @@ -510,8 +253,7 @@ void CountSumBlock(FILEINFO* p_fi, uint8_t block_indx, uint8_t *p_buffer, uint16  } -unsigned char buff[32768]; - +/************************************************************************/  uint32_t GetOverallLen(FILEINFO *p_fi) {  	uint32_t overall_len = 0;  	uint8_t block_num = p_fi->fi_numblocks; @@ -521,6 +263,7 @@ uint32_t GetOverallLen(FILEINFO *p_fi) {  	return overall_len;  } +/************************************************************************/  void RecvSCP(void) {  	int recv_phase = 0;			// 0 - fileinfo, 1 - blok 16kiB, 2 - posledni blok  	uint8_t block_index = 0; @@ -570,8 +313,6 @@ void RecvSCP(void) {  								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; @@ -622,8 +363,10 @@ void RecvSCP(void) {  	printf ("\n\nulozeno...\n");  } +/************************************************************************/  void SendSCP(void) {  	FILE *tap_fd; +	char *bname, *basec;			// pinter na kopii nazvu souboru - basename  	unsigned int err, no, len;  	struct stat st;  	FILEINFO *p_fileinfo = &fileinfo; @@ -647,10 +390,17 @@ void SendSCP(void) {  		err = errno;  		error(1, err, "can't open input file");  	} -	printf ("Soubor %s delky: %ld\n", tap_file, st.st_size); +	if (st.st_size == 0) { +		printf ("Zero length of file. End\n"); +		return; +	} +	printf ("File %s, length: %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)); +	basec = strdup (tap_file); +	bname = basename (basec); + +	memcpy(p_fileinfo->fi_name, bname, strlen(bname));  	file_len = (uint32_t) st.st_size;  	while (file_len) {  		len = fread(buff, 1, 16384, tap_fd);			// precti 16kiB dat @@ -664,7 +414,7 @@ void SendSCP(void) {  	CountFileInfoChecksum(p_fileinfo);  	odeslano = write (serial_fd, (void*)p_fileinfo, sizeof(fileinfo));  	tcdrain(serial_fd); -	printf("Fileinfo sent...\n"); +	printf("Fileinfo sent with filename: %s\n", bname);  	// TODO Cekat pauzu mezi bloky  	usleep (wait_ms * 1000); @@ -694,6 +444,8 @@ void SendSCP(void) {  	fclose(tap_fd);  } +/************************************************************************/ +/************************************************************************/  int main(int argc, char** argv, char** env)  {  	// osetreni breaku ^C @@ -705,7 +457,7 @@ int main(int argc, char** argv, char** env)  	// nastaveni serioveho portu  	struct termios oldtio, newtio;  	inp_indx = 0; -	if (argc < 3) { +	if (argc < 2) {  		printf("You must specify the Serial device and file\n");  		usage();  		exit(1); @@ -719,42 +471,38 @@ int main(int argc, char** argv, char** env)  	}  	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; +			newtio.c_cflag = B115200 | CS8 | CLOCAL | CREAD | CRTSCTS;  			break;  		case 57600: -			newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; +			newtio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | CRTSCTS;  			break; +		default: +			baud_rate = 38400;  		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; +			newtio.c_cflag = B19200 | CS8 | CLOCAL | CREAD | CRTSCTS;  			break;  		case 9600: -			newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; +			newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD | CRTSCTS;  			break;  		case 4800: -			newtio.c_cflag = B4800 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; +			newtio.c_cflag = B4800 | CS8 | CLOCAL | CREAD | CRTSCTS;  			break;  		case 2400: -			newtio.c_cflag = B2400 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; +			newtio.c_cflag = B2400 | CS8 | CLOCAL | CREAD | CRTSCTS;  			break;  		case 1200: -			newtio.c_cflag = B1200 | CS8 | CLOCAL | CREAD | CSTOPB | CRTSCTS; +			newtio.c_cflag = B1200 | CS8 | CLOCAL | CREAD | CRTSCTS;  			break;  	} -	newtio.c_cflag |= CRTSCTS; +	newtio.c_cflag |= CRTSCTS;		// CSTOPB - dva stop bity NEE  	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;  	newtio.c_oflag = 0; -// 	newtio.c_oflag &= ~OPOST; -	newtio.c_lflag = 0; //NOFLSH; +	newtio.c_lflag = 0;  	newtio.c_cc[VMIN] = 0;  	newtio.c_cc[VTIME] = 10;  	tcsetattr(serial_fd, TCSANOW, &newtio); @@ -762,20 +510,11 @@ int main(int argc, char** argv, char** env)  	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(); -		} +	// serial copy activated +	if (is_scp_read) { +		RecvSCP();  	} 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 -		} +		SendSCP();  	}  	close (serial_fd);  	return 0; | 
