Subject: pl19: serial communication via COM1:
From: [email-masked] (Frank Baumgart)

3 Mar 1998 05:08:48 -0800
Message-ID: <[email-masked]>
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="------------C813F10E372EC4054DC38A89"
To: [email-masked]

This is a multi-part message in MIME format.
--------------C813F10E372EC4054DC38A89
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached program fails with cygwin32 pl19 as follows:
   (see strace-output-attachment also)

   - nonblocking mode does not seem to be set (1)
     after select() (see below) returns, read() is called but blocks
     - if we try to read more data than is available
     - if no data is available though select() supposes so

   - select() does not time out correctly (2)
     Even with no input from the read-fd(s) available, time out does
     not occur, instead, select() returns 1 as if data was available.
     As strace shows, the file descriptor is considered as follows:
     "cygwin32_select: added fd 3 to always_read"
     which is wrong, even in non-blocking mode.
     fhandler.cc/h shows no special case for "COMx:"/"AUX:" "files" 
     (well, devices), defaulting to a handler returning 1 meaning 		    
always_read.
     I do not know how to fix this but I hope this information is 
     sufficient. (Sergey, could you please make a binary cygwin19.dll 
     with patches available, I do have difficulties to build the dll 
     myself)

   - alarm (which should show predictable behaviour while not used
     around a select() call) does not "fire", when read() blocks. (3)

   - (not demonstrated here)
     when trying to set communication parameters with tcsetattr(), 
     cygwin fails with "no tty device" (no quote, just sense);
     CYGWIN32 does not contain the term "tty", though setting "tty" 
     does not make any difference. (I think it is just for console 
     handling anyway?)
     Interestingly, strace shows that isatty(fd) returns true.

   nb.: this program works with HP-UX 10.20 and Linux 2.0/2.1 libc5

   my environment:
   - cygwin32 pl19 has been installed as a cross compiler on a Linux 
     machine running 2.0.33/2.1.84 with libc 5.4.33
   - the executables are exported via samba to the NT 4.0 SP3 machine
   - output is examined with "vnc" (allows to display/work with a 
     Win'95/NT screen on a (UNIX)/X11 machine - something like WinDD 
     I think, just free but slow)
   - there is no old pl18 around
--------------C813F10E372EC4054DC38A89
Content-Type: text/plain; charset=us-ascii; name="modem.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="modem.c"

/*
	modem - serial communication test program
	connect a modem to COM1: and invoke with "modem at-command" or "modem"

	[email-masked] (Frank Baumgart), 03.03.1998
*/

#define DEBUG	1

#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>

#if defined(hpux)
#include <termio.h>
#include <sys/modem.h>
#include <sys/termiox.h>
#endif

void set_baudrate(int fd,long rate);
void modem_read_answer(int fd);
void alarm_handler(int);

#if defined(WINNT)
#define PORT		"COM1:"
#elif defined(hpux)
#define PORT		"/dev/tty0p0"
#else
#define PORT		"/dev/cua0"
#endif

int main(int argc,char *argv[])
{
	int fd;

	fd = open(PORT,O_RDWR | O_NONBLOCK);				/* (1) */
	if (fd < 0)
	{
		printf("can not open device %s\n",PORT);
		return 1;
	}
#if 0
	// fails using tc[sg]etattr() complaining about "no tty device"
	set_baudrate(fd,B38400);
#endif
	if (argc == 2)
	{
		puts(argv[1]);
		write(fd,argv[1],strlen(argv[1]));
		write(fd,"\r\n",2);
	}
	else
	{
		puts("AT&V");
		write(fd,"AT&V\r\n",6);
	}
	sleep(1);
	modem_read_answer(fd);

	return 0;
}

void modem_read_answer(int fd)
{
	fd_set rset;
	struct timeval tv;
	int ret;

	do
	{
		FD_ZERO(&rset);
		FD_SET(fd,&rset);

		/* timeout after 3 s */
		tv.tv_sec = 3;
		tv.tv_usec = 0;

		ret = select(fd+1,&rset,NULL,NULL,&tv);			/* (2) */

#if DEBUG
		// show, that select() does return 1 even if no data is available
		// and a timeout should occur
		printf("select = %d\n",ret);

		// even if a timeout should occur, the timeout value
		// in tv remains 3 s + 0 us.
		// (yes, I know this is Linux specific behaviour, considered bad etc.;
		// just checking for a workaround)
		printf("s:u = %ld:%ld\n",tv.tv_sec,tv.tv_usec);
#endif

		if (ret && FD_ISSET(fd,&rset))
		{
			long bytes;
			char answer[100];

			// alarm never fires when read() blocks (3)
			signal(SIGALRM,alarm_handler);
			alarm(5);

#if DEBUG
			printf("\nread: ");
			fflush(stdout);
#endif
			// reading less than 4 bytes (trigger level) per read() results 
			// in data loss using HP-UX 10.20; no problem with HP-UX 9.x
			// (just a side note)
			bytes = read(fd,answer,20);
#if DEBUG
			printf("%ld\n",bytes);
#endif
			if (bytes < 0)
			{
				puts("read error!");
				return;
			}
			if (bytes == 0)
			{
				// NEVER reached when data was ONCE available.
				// Only when deleting the sleep() statement far above and given, 
				// the modem does not answer until the first read/select, which 
				// is likely, read() returns 0
				puts("no data?!");
				return;
			}
			write(0,answer,bytes);
		}
		else
		{
			// never happens with cygwin32pl19
			puts("timeout!");
			return;
		}
	}
	while (1);
}

void alarm_handler(int dummy)
{
	// never gets called with cygwin32pl19
	puts("alarm!");
}

--------------C813F10E372EC4054DC38A89--

-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".