From: id@cs.mcgill.ca (Ian Duncan)
Subject: Is it NeXT or me: serial misunderstandings
Followup-To: comp.sys.next.programmer
Organization: McGill University Computing Centre
Date: Sat, 11 Apr 1992 01:05:21 GMT

I'm trying to get a decent serial setup working with a NeXT Cube. One of the
biggest problems I'm having is getting the modem control signals functioning
so that the modem and system can work without constant intervention.
On my reading of the documentation I should automatically see DTR asserted
on an open() when the 'cu' class of devices are used. This doesn't happen.

In an effort to get the bottom of this I sketched the attached bit of code
with these disappointing results: 
# cc -o portstate portstate.c
# portstate
speed in(13) & out(13), mode 216
modem control state: 0
modem control state: 0
tried to set modem control state: 2
and the new modem control state: 0

Note that I am running this as root.

So can someone tell me how I'm wasting my time. Either I've misunderstood
something fundemental or the serial driver is broken. The machine is an
up-to-date Cube running the 2.1 OS. For not very good reasons I manually
applied the upgrade so I may have screwed it up. I am focused on the OS
version since I recall mention of bugs in the 2.0 serial driver.

//----- cut here -----

// to muck about with with modem port settings.

/*
**	The following is lifted straight from man page zs(4):
**
**                  When /dev/cua is opened, the device driver
**                  asserts DTR and does NOT block waiting for
**                  the modem to assert DCD.  No action is taken
**                  by the driver when the modem asserts or de-
**                  asserts DCD.
**
**                  /dev/cua is typically used by programs like
**                  "uucp" and "tip" that need access to auto-
**                  dial modems.
**                  
**                  [ ... ]
**
**                  /dev/cufa (/dev/cufb) operates identically to
**                  /dev/cua except that RTS/CTS flow control is
**                  supported on 68040-based systems. 
*/

#include <libc.h>
#include <stdio.h>
#include <errno.h>
#include <sys/ioctl.h>

struct sgttyb tt;

main(char *argv[], int argc)
{
int fd, it, c;
	if ((fd = open("/dev/cufa", O_RDWR|O_NDELAY)) > 0)
	{
	// get the initial state of device
		if (-1 == ioctl(fd, TIOCGETP, &tt))
			fprintf(stderr, 
				"error: ioctl(TIOCGETP) failed on %d\n",
				errno
				);
		else
		{	fprintf(stdout, 
				"speed in(%d) & out(%d), mode %d\n",
			        tt.sg_ispeed,
				tt.sg_ospeed,
				tt.sg_flags
				);
		}
		if (-1 == ioctl(fd, TIOCMODG, &it))
			fprintf(stderr, 
			"error: ioctl(TIOCMODG) failed on %d\n",
			errno
			);		
		else
			fprintf(stdout, "modem control state: %d\n", it);

	// try for a change -- set DTR, hopefully ???
		if (-1 == ioctl(fd, TIOCSDTR))
			fprintf(stderr,
				"error: ioctl(TIOCSDTR) failed on %d\n",
				errno);		
		else
			if (-1 == ioctl(fd, TIOCMODG, &it))
				fprintf(stderr, 
				"error: ioctl(TIOCMODG) failed on %d\n",
				errno
				);	
			else
				fprintf(stdout, 
					"modem control state: %d\n",
					it
					);

	// now try a different approach
		it |= TIOCM_DTR;
		if (-1 == ioctl(fd, TIOCMODS, &it))
			fprintf(stderr,
				"error: ioctl(TIOCMODS) failed on %d\n",
				errno);		
		else
			fprintf(stdout,
				"tried to set modem control state: %d\n",
				it);		
		
	// wait a few seconds and see what happened
		sleep(2);
		if (-1 == ioctl(fd, TIOCMODG, &it))
			fprintf(stderr,
				"error: ioctl(TIOCMODG) failed on %d\n",
				errno);		
		else
			fprintf(stdout,
				"and the new modem control state: %d\n",
				it);		
		
		close(fd);
	}
	else
	{
		fprintf(stderr, "failed on open\n");
	}
	exit(0);
}

// ----- cut here -----


-- 
   ...   ian   <id@cc.mcgill.ca>
Ian Duncan -- McGill University Computing Center -- +1.514.398.3714