need a linux floppy

Eric W. Biederman ebiederman at lnxi.com
Thu Dec 9 21:45:01 CET 2004


"Adam Talbot" <talbotx at comcast.net> writes:

> Hummm.  Got both tomsrtbt and coyote Linux running.  coyote Linux is very
> nice and I have other apps for it.  But none of those had minicom on them.
> Any other ideas?

cat /dev/ttyS0 
cat > /dev/ttyS0

Should just about do it.

Or for something a little more complete.

Eric

/* To compile run: gcc -g -O -Wall serial_echo.c -o serial_echo */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define BUFFER_SIZE (1024)
#define BUFFER_RESERVE 8


speed_t get_baud(int wanted)
{
	speed_t result = B0;
	switch(wanted) {
	case 50: result = B50; break;
	case 75: result = B75; break;
	case 110: result = B110; break;
	case 134: result = B134; break;
	case 150: result = B150; break;
	case 200: result = B200; break;
	case 300: result = B300; break;
	case 600: result = B600; break;
	case 1200: result = B1200; break;
	case 1800: result = B1800; break;
	case 2400: result = B2400; break;
	case 4800: result = B4800; break;
	case 9600: result = B9600; break;
	case 19200: result = B19200; break;
	case 38400: result = B38400; break;
	case 57600: result = B57600; break;
	case 115200: result = B115200; break;
	case 230400: result = B230400; break;
	case 460800: result = B460800; break;
	case 500000: result = B500000; break;
	case 576000: result = B576000; break;
	case 921600: result = B921600; break;
	case 1000000: result = B1000000; break;
	case 1152000: result = B1152000; break;
	case 1500000: result = B1500000; break;
	case 2000000: result = B2000000; break;
	case 2500000: result = B2500000; break;
	case 3000000: result = B3000000; break;
	case 3500000: result = B3500000; break;
	case 4000000: result = B4000000; break;
	}
	return result;
}


#define ESC_CHAR '\x1e'
int do_inbuf_actions(char *in_buff,  int len, int fd_serial, 
	char *input_file, int *fd_input_file)
{
	static int in_esc = 0;
	int i;
	for(i = 0; i < len ;) {
		if (!in_esc) {
			if (in_buff[i] == ESC_CHAR) {
				in_esc = 1;
				memmove(in_buff, in_buff +1, len - i -1);
				len--;
				continue;
			}
		}
		if (in_esc) {
			if (in_buff[i] == ESC_CHAR) {
				in_esc = 0;
				i++;
				continue;
			}
			else if (in_buff[i] == '\x3') {
				exit(0);
			}
			else if (in_buff[i] == 'b') {
				tcsendbreak(fd_serial, 0);
			}
			else if (in_buff[i] == 'f') {
				int fd;
				fd = open(input_file, O_RDONLY | O_NONBLOCK);
				if (fd < 0) {
					*fd_input_file = -1;
					fprintf(stderr, "Cannot open %s %s\n",
						input_file, strerror(errno));
				}
				else {
					*fd_input_file = fd;
				}
#if 0
				do_transmit_file(fd_serial, input_file);
#endif
			}
			memmove(in_buff, in_buff +1, len -i -1);
			len--;
			in_esc = 0;
			continue;
		}
		i++;
	}
	return len;
}

static struct termios initial_term_options;
void do_terminal_cleanup(void)
{
	int result;
	result = tcsetattr(STDOUT_FILENO, TCSANOW, &initial_term_options);
	fprintf(stderr, "Exiting due to error %d -> %s\n",
		errno, strerror(errno));
}
void usage(int argc, char **argv)
{
	fprintf(stderr, "Usage: %s [[[[[device] speed] none|hard|soft] ro|rw]\n",
		argv[0]);
	exit(1);
}

int main(int argc, char *argv[])
{
	int fd_serial;
	char serial_port[] = "/dev/ttyS0";
	char *port;
	speed_t speed;
	struct pollfd fds_wait[3], fds_data_wait[3], *fds;
	int result;
	char out_buff[BUFFER_SIZE], in_buff[BUFFER_SIZE];
	int out_buff_fill, in_buff_fill;
	struct termios serial_options, term_options;
	char *input_file;
	int fd_input_file;
	int hard_flow_control;
	int soft_flow_control;
	int read_only;

	port = serial_port;
	speed = B115200;
	input_file = 0;
	hard_flow_control = 0;
	soft_flow_control = 0;
	read_only = 1;
	fd_input_file = -1;
	if (argc >= 2) {
		port = argv[1];
	}
	if (argc >= 3) {
		speed = get_baud(atoi(argv[2]));
	}
	if (argc >= 4) {
		if (strcmp(argv[3], "none") == 0) {
			hard_flow_control = 0;
			soft_flow_control = 0;
		}
		else if (strcmp(argv[3], "hard") == 0) {
			hard_flow_control = 1;
		}
		else if (strcmp(argv[3], "soft") == 0) {
			soft_flow_control = 1;
		}
		else {
			usage(argc, argv);
		}
	}
	if (argc >= 5) {
		if (strcmp(argv[4], "ro") == 0) {
			read_only = 1;
		}
		else if (strcmp(argv[4], "rw")  == 0) {
			read_only = 0;
		}
		else {
			usage(argc, argv);
		}
	}
	if (argc >= 6) {
		input_file = argv[5];
	}
	       
	fd_serial = open(port, O_RDWR | O_NONBLOCK);
	if (fd_serial < 0) {
		fprintf(stderr, "Can't open %s\n", port);
		exit(1);
	}
	
	result = tcgetattr(STDOUT_FILENO, &initial_term_options);
	if (result < 0) {
		fprintf(stderr, "result < 0 errno = %d -> %s\n",
			errno, strerror(errno));
		exit(1);
	}
	atexit(do_terminal_cleanup);
	term_options = initial_term_options;
	term_options.c_iflag &= (ISTRIP | IGNBRK );
	term_options.c_cflag &= ~(CSIZE | PARENB | IXON | IXOFF | IXANY);
	term_options.c_cflag |= (CS8 |CREAD) | 
		((soft_flow_control)?(IXON|IXOFF|IXANY): 0);
	term_options.c_lflag &= 0;
	term_options.c_cc[VMIN] = 1;
	term_options.c_cc[VTIME] = 0;
	result = tcsetattr(STDOUT_FILENO, TCSANOW, &term_options);
	if (result < 0) {
		fprintf(stderr, "result < 0 errno = %d -> %s\n",
			errno, strerror(errno));
		exit(1);
	}
	

	result = tcsetattr(STDIN_FILENO, TCSANOW, &term_options);
	if (result < 0) {
		fprintf(stderr, "result < 0 errno = %d -> %s\n",
			errno, strerror(errno));
		exit(1);
	}
	
	
	result = tcgetattr(fd_serial, &serial_options);
	if (result < 0) {
		fprintf(stderr, "result < 0 errno = %d -> %s\n",
			errno, strerror(errno));
		exit(1);
	}

	serial_options.c_iflag = 0;
	serial_options.c_oflag = 0;
	serial_options.c_cflag = CS8 | CREAD | ((hard_flow_control)?CRTSCTS:0);
	serial_options.c_lflag = 0;
	cfsetispeed(&serial_options, speed);
	cfsetospeed(&serial_options, speed);

	result = tcsetattr(fd_serial, TCSANOW, &serial_options);
	if (result < 0) {
		fprintf(stderr, "result < 0 errno = %d -> %s\n",
			errno, strerror(errno));
		exit(1);
	}

	fds_wait[0].fd = fd_serial;
	fds_wait[0].events = POLLIN;
	fds_wait[0].revents = 0;
	fds_wait[1].fd = STDIN_FILENO;
	fds_wait[1].events = POLLIN;
	fds_wait[1].revents = 0;
	fds_wait[2].fd = -1;
	fds_wait[2].events = 0;
	fds_wait[2].revents = 0;
	
	fds_data_wait[0].fd = fd_serial;
	fds_data_wait[0].events = POLLIN | POLLOUT;
	fds_data_wait[0].revents = 0;
	fds_data_wait[1].fd = STDIN_FILENO;
	fds_data_wait[1].events = POLLIN;
	fds_data_wait[1].revents = 0;
	fds_data_wait[2].fd = STDOUT_FILENO;
	fds_data_wait[2].events = POLLOUT;
	fds_data_wait[2].revents = 0;

	
	out_buff_fill = 0;
	in_buff_fill = 0;
	fds = fds_wait;
	
	for (;;) {
		result = poll(fds, 3, -1);
		if (result < 0) {
			break;
		}
		if ((fds[0].revents & POLLIN) && (sizeof(out_buff) > out_buff_fill)){
			result = read(fd_serial, out_buff + out_buff_fill, 
				sizeof(out_buff) - out_buff_fill);
			if (result > 0) {
				out_buff_fill += result;
			}
		}
		if ((fds[1].revents & POLLIN) && (sizeof(in_buff) > in_buff_fill)) {
			result = read(STDIN_FILENO, in_buff + in_buff_fill,
				sizeof(in_buff) - in_buff_fill);
			if (result > 0) {
				int bytes;
				bytes = do_inbuf_actions(in_buff + in_buff_fill, result, fd_serial, input_file, &fd_input_file);
				if (read_only) 
					bytes = 0;
				in_buff_fill += bytes;
			}
		}
		if ((fd_input_file >= 0) 
			&& ((sizeof(in_buff) - BUFFER_RESERVE) > in_buff_fill)) {
			result = read(fd_input_file, in_buff + in_buff_fill,
				(sizeof(in_buff) - BUFFER_RESERVE) - in_buff_fill);
			if (result > 0) {
				in_buff_fill += result;
			}
			else if (result == 0) {
				close(fd_input_file);
				fd_input_file = -1;
			}
		}
		if ((fds[2].revents & POLLOUT) && out_buff_fill) {
			result = write(STDOUT_FILENO, out_buff, out_buff_fill);
			if (result > 0) {
				out_buff_fill -= result;
				if (out_buff_fill) {
					memmove(out_buff, out_buff + result, out_buff_fill);
				}
			}
		}
		if ((fds[0].revents & POLLOUT) && in_buff_fill) {
			result = write(fd_serial, in_buff, in_buff_fill);
			if (result > 0) {
				in_buff_fill -= result;
				if (in_buff_fill) {
					memmove(in_buff, in_buff + result, in_buff_fill);
				}
			}
		}
		fds = (in_buff_fill || out_buff_fill || (fd_input_file >= 0))? 
			fds_data_wait : fds_wait;
	}
	return 0;
}



More information about the coreboot mailing list