SUMMARY: Sun IPX serial port setup problem

From: allan branscomb (
Date: Wed Dec 16 1992 - 09:17:50 CST


Thank you all very much for your prompt and generous help with my problems
including my misunderstanding of UNIX shells. My background in other operating
systems continues to mislead me in such things as the handling of the standard
input and output files, the domains for which such definitions are active, and
the way in which the UNIX process structure affects these definitions for various
forms of command invocation - sub shells, etc. Thanks again for your
patience and advice.

I have summarized the responses into 'programmatic' and 'command line' categories
below. A row of plus signs (++++++) separates the individual suggestions.

In our case I put a data analyzer on the serial line so I could be certain of
both the basic communications parameters and how the data were being handled - the cariage return/line feed issues and the like.

One thing that impressed me greatly was the variation between operating system
versions, and other factors about which I am not clear. On the Sun IPX with
version 4.1.3 of the OS, and using the c-shell, the only version of stty that
would set the non-login port correctly is the System V version: (/usr/5bin/stty
parenb -parodd cs7 cstopb nl;sleep 100000) < /dev/ttya &. The standard BSD
version of stty would only set the login port. On the inquiry side, stty would
report on /dev/ttya if the I/O redirection operator pointed TO the port e.g.
stty -a > /dev/ttya, but would report the login port if redirection was stated in
the way that made intuitive sense to me: stty -a < /dev/ttya; cat > /dev/ttya
sends data to the port, and cat < /dev/ttya accepts data from it.

None of these options would work on some Sun 386i's avaialable to me (V4.0.2).

So, although we have our tablet working fine, I suspect that the generality of the solution I've cobbled together is limited.



I. Programmatic

think this is what you want
  Output modes
     The c_oflag field specifies the system treatment of output:

          ONLCR 0000004 Map NL to CR-NL on output.
          OCRNL 0000010 Map CR to NL on output.
          ONLRET 0000040 NL performs CR function.

from the man page on TERMIO, ONLCR might mean having an extra NL, but it
may work or you could try not setting OCRNL and see if CR goes
straight through. You will need to use the stty (man 3 stty) C

        Boyd Fletcher


I'm not sure if this will help; I wrote such a program a long time ago
to use a Texas Instruments HI-9018 digitizing tablet on a Sun. Note the
program uses CGI graphics. This has been abandoned by Sun but you might find
it in an "old" directory or should be able to either comment it out or
replace it. Anyway it might give you some ideas/ a starting point.
Certainly it worked for us a couple of years ago when we needed to do some

/* HI 9018 digitizer
 * To compile: cc -O -o hi9018 hi9018.c -lcgi -lsunwindow -lpixrect -lm
 * NOTE: Assumes ASCII_2 mode to circumvent hardware bug
 * (else you will probably get a sscanf error)
 * Uses cgi plotting to current Sun window
 * invocation: hi9018 [-b baud] [-d] [-n] [-z zval] [-p]
 * -b baud : set baud rate to baud; default is 4800
 * -d : set debug mode, print out extra info
 * -n : don't strip out tag bit. Default is to strip.
 * -z zval : add a constant z coordinate zval to x y [tag] output
 * -p : create crude cgi plot to Sun window; tag = 1 is 'pen down',
 * tag = 2,3,4 is 'pen up'. The first two points digitized MUST
 * be the upper right and lower left corners to initialize the
 * plot scaling. */
#include <stdio.h>
#include <sgtty.h>
#include <signal.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/ttydev.h>
#define PORT "/dev/ttyb"
#define DEFBAUD 4800
#define TRUE 1
#define FALSE 0
static char *usage = "usage: hi9018 [-b baud] [-d] [-n] [-z zval] [-p]";
static char *badstr = "possible bad input:";
/* Global for catcher() to see */
static int plot = FALSE;

int argc; char *argv[];
    register int f,nb; int urx,ury,llx,lly,debug=FALSE;
    int baud= DEFBAUD,strip = TRUE,catcher(),x,y,tag,first=TRUE;
    char buf[80], *s, *z = NULL, tagl; struct sgttyb stty;
    for (f = 1; f < argc; f++)
        switch (*(argv[f]+1)) {
           case 'n': strip = FALSE; break;
           case 'b': baud = atoi(argv[++f]); break;
           case 'd': debug = TRUE; break;
           case 'z': z = argv[++f]; break;
           case 'p': plot = TRUE; break;
           default : exit(fprintf(stderr,"%s\n",usage)); }
    if ((f = open(PORT,O_RDWR,0)) <= 0) exit(perror("open"));
    if (ioctl(f,TIOCGETP,&stty) < 0) exit(perror("TIOCGETP"));
    switch (baud) {
       case 1200: stty.sg_ispeed = stty.sg_ospeed = B1200; break;
       case 2400: stty.sg_ispeed = stty.sg_ospeed = B2400; break;
       case 4800: stty.sg_ispeed = stty.sg_ospeed = B4800; break;
       case 9600: stty.sg_ispeed = stty.sg_ospeed = B9600; break;
       case 19200: stty.sg_ispeed = stty.sg_ospeed = B19200; break;
       default: exit(fprintf(stderr,"%d not valid speed\n",baud)); }
    stty.sg_flags &= ~(ECHO|CRMOD); stty.sg_flags |= TANDEM;
    if (ioctl(f,TIOCSETP,&stty) < 0) exit(perror("TIOCSETP"));
    signal(SIGTERM,catcher); /* set up clean exit for kill modes */
    signal(SIGINT,catcher); signal(SIGQUIT,catcher);
    /* if real-time plot then
     * 1) get upper right (X,Y)
     * 2) get lower left (X,Y)
     * 3) initialize cgi plot mode. */
    if (plot) {
        if ((nb = read(f,buf,sizeof(buf)-1)) > 0 )
          { if (sscanf(buf,"%c%d%d\n",&tagl,&urx,&ury) != 3)
              exit(perror("sscanf")); }
        else exit(perror("ur read"));
        if ((nb = read(f,buf,sizeof(buf)-1)) > 0 )
          { if (sscanf(buf,"%c%d%d\n",&tagl,&llx,&lly) != 3)
              exit(perror("sscanf")); }
        else exit(perror("ll read"));
        if (debug)
          { printf("%s\n",buf);
            printf(" %d %d %d %d\n",urx,ury,llx,lly); }

    while (TRUE) /* Suck up input from digitizer (until signal occurs) */
      if ((nb = read(f,buf,sizeof(buf)-1)) > 0 )
        if (sscanf(buf,"%c%d%d\n",&tagl,&x,&y) != 3)
        tag= ((int) tagl) >> 4; /* See Appendix D-2 */
        if ((tag % 2) == 0) tag -=3; else tag-- ;
        if (debug)
          { printf("%s\n",buf);
            printf(" %c %d %d %d\n",tagl,tag,x,y); }
        if (plot) {
            if (first == 0) plotpt(x,y,tag);
            else { wininit(urx,ury,llx,lly,x,y); first= FALSE; } }
        if (z == NULL) {
          if (strip) printf("%6d %6d \n",x,y);
          else printf("%6d %6d %d \n",x,y,tag); }
        else {
          if (strip) printf("%6d %6d %s \n",x,y,z);
          else printf("%6d %6d %d %s \n",x,y,tag,z); }
      else if (nb < 0) perror("read");

/* Catch termination signal and exit gracefully */
catcher(sig,code,scp) /*ARGSUSED*/
int sig,code; struct sigcontext *scp;
  { if (plot) endwin();
    printf("\nhi9018 terminating on signal %d\n",sig);
    exit(0); }

#include <cgidefs.h>
Ccoorlist plotlist;
Ccoor plot_coords[2], vpll, vpur, lower, upper;
Cint name;

int urx,ury,llx,lly,x1,y1;
  int xdif, ydif;
  Cvwsurf device;
  open_vws(&name, &device);
  upper.x= urx; upper.y= ury;
  lower.x= llx; lower.y= lly;
  xdif= (urx - llx)/ 20; /* 5% boundary */
  ydif= (ury - lly)/ 20; /* (Outliers will be clipped) */
  vpll.x = llx - xdif; vpll.y= lly - ydif;
  vpur.x = urx + xdif; vpur.y= ury + ydif;
  vdc_extent(&vpll, &vpur);
  rectangle(&lower, &upper);
  plot_coords[0].x= x1; plot_coords[0].y= y1;
  plotlist.n = 2;

int x,y,tag;
  if (tag == 1) /* pen down, move to x,y */
    plot_coords[1].x= x; plot_coords[1].y= y;
    plotlist.ptlist = plot_coords;
    plot_coords[0].x= plot_coords[1].x;
    plot_coords[0].y= plot_coords[1].y;
  else /* pen up, move to x,y */
    { plot_coords[0].x= x; plot_coords[0].y= y; }

{ close_vws(name); close_cgi(); }


Your original is attached below:
After you open the device for write, do an ioctl (using a termios struct)
set c_oflag = (c_oflat | ONLRET) & (~OCRNL)

Michael Baumann
Radiation Research Lab |Internet:
Loma Linda Universtiy Medical Center | UUCP: ...ucrmath!proton!baumann
Loma Linda, California. (714)824-4077|


II. Command Line:

As you have probably also noted, Sun delivers 2 versions of stty which
differ in functionality in some ways. /bin/stty is incapable of being
redirected on input, while /usr/5bin/stty can be redirected. That is,

/bin/stty < /dev/ttya fails to read the status of /dev/ttya
                                but instead gives the same as "stty"

/usr/5bin/stty < /dev/ttya does give the status of ttya

Unfortunately, I was not successful in using the 5bin version to affect
on an output-redirected device, even if I had a process holding the device
open. (ie, the moral equivalent of cat > /dev/ttya running in another
window). I am not clear why /usr/5bin/stty onlcr > /dev/ttya does not
seem to work. CAVEAT: I don't have any serial devices at my disposal,
so I was testing on ports without anything "live" plugged in. This might
invalidate my efforts.

I hope that some other sun-managers with more recent serial interfacing
experience can point you at a package to solve your problem, otherwise
I'm afraid that command-line parsing and ioctl calls within your application
package is the approach I'd be forced to take.

Best of luck, and I'll be looking forward to learn from the net's collective


Tom Slezak
Human Genome Center, L-452
Lawrence Livermore National Lab
7000 East Ave. Livermore, CA 94550
email: (
phone: (510) 422-5746 fax: (510) 423-3608


from stty(1) manual page:

     stty sets certain terminal I/O options for the device that
     is the current standard output. Without arguments, it
     reports the settings of certain terminal options for the
     device that is the standard output; the settings are
     reported on the standard error.
     Detailed information about the modes listed in the first
     five groups below may be found in termio(4). Options in the
     last group are implemented using options in the previous
     groups. Note: many combinations of options make no sense,
     but no sanity checking is performed.
     stty sets or reports terminal options for the device that is
     the current standard input; the settings are reported on the
     standard output.

To have stty report on, or control an arbitrary serial port, just use
the usual shell redirection operator so that stty's standard input or
output (depending on which flavor of stty you use) is the port.
I prefer System V, so I would use:

        /usr/5bin/stty -onlcr </dev/ttya

Remember that a serial port reverts to its default settings whenever
no process has it open, so you probably need to construct a shell
script that does something like this:

/usr/5bin/stty -onlcr
) </dev/ttya


You have one. From the man page for stty:

> stty sets certain terminal I/O options for the device that
> is the current standard output.

Thus, for example, `stty -ocrnl >/dev/ttya' will set parameters for port `a'.

Rich Schultz


"stty" doesn't act on "the current session device", except for a few
operations such as "stty size", "stty speed", and "stty -g".
"/usr/bin/stty" acts on its *standard output*, and "/usr/5bin/stty" acts
on its *standard input*.

Both the standard input and output, *by default*, will be the current
session device; however, you can redirect them with the standard UNIX
shell redirection operations, e.g.

        stty -onlcr >/dev/ttya # "stty" here is assumed to be "/usr/bin/stty"


        /usr/5bin/stty -onlcr </dev/ttya



stty options | /dev/ttyx

where ttyx is your port



You can use stty to configure any serial tty by making it the standard OUTPUT on the command line :

  stty ..... > /dev/tty*

similarly to read the current settings use the same redirection :

  stty -a > /dev/tty*

I have writen various scripts to control arbitrary serial ports this way.
Make sure you have write access to the required device of course.

Peter Farmer e-mail:
Programmer phone: +61 6 249 3434
Department of Computer Science, fax: +61 6 249 0010
2nd floor, Crawford Building,
Australian National University

stty applies any changes to stdout, while printing to stderr (if you
are not running sys V emulation), so if you wish to change something
on, say /dev/ttyb try the following:

; stty (args) > /dev/ttyb


Alan Hargreaves (VK2KVF), Uni of Newcastle, UCS.
Ph: +61 49 215 512 Fax: +61 49 684 742 ICBM: 32 53 44.6 S / 151 41 52.6 E

Software Bloat - Any UNIX(tm) after Version 7. (


You can make stty mess with an arbitrary port via of the following (I forget which):

stty -options > /dev/ttynn # BSD, probably Sun stty -options < /dev/ttynn # SysV, probably not Sun

If a program doesn't hold the port open, it will revert to some other state after you set it. So, open the port with a program before you do the stty:

(sleep 2147483646 > /dev/ttynn) &

Also make sure that no other program is trying to mess with the port, i.e. a getty started from init.

"To use Fred Brooks' terminology, people keep handing me programs when I'm expecting programming products." -- Me ------------------------------------------------------------------------------- Brian Bartholomew - - Univ. of Florida Dept. of Mathematics


The standard way that you do this is to create a session which sets the parameters you want then hangs around for a long time, eg run something like this in /etc/rc.local:

(stty -onlcr; sleep 10000000) > /dev/ttya &

Just add the specific stty commands that you need. 10 million seconds is about 5 months so the command should never exit.

regards, -- Glenn Satchell ups!glenn@fourx.Aus.Sun.COM | Uniq Professional Services Pty Ltd ACN 056 279 335 | "The answer is no, PO Box 70, Paddington, NSW 2021, (Sydney) Australia | and I'll negotiate Phone: +61-2-360-7434 Fax: +61-2-331-2572 | from there." "Sun Accredited System Consultants" |


I don't have a 4.1.3 system handy, but at least on 4.1.2 stty operates on the device which is its standard output. (The Sys5 version operates on its standard input.) It "should" therefore be possible to apply either version of stty to an arbitrary port (provided, of course that there isn't a getty enabled on it to fight with you for control).

If the problem is that the driver is resetting to defaults on the last close of the device, you could do something like

sleep 60 > /dev/{whatever} &

so that the sleep process will hold the port open while other things happen, thereby keeping any other process' close operation from being the last one.


Try "stty < /dev/ttya" ...


cheesy way:

% ( stty -NLCR > /dev/ttyb ; command opt1 opt2 opt3)

stty changes the line discipline for whatever device is the current stdout.

two cleaner ways of doing this: (a) write a streams module you can push on top of the tty stack to do the conversion (b) close your controlling terminal, then open the tty port, then use the ioctl()s from within the interface program to set the line discipline.

(b) gets my vote, but not knowing what the code looks like, the cheesy solution might have to be it.



> ... and *for the current session device*, stty can handle the job on the > command line.

What does that mean ? You should be able do set the tty characteristics of any serial port with commands like "(stty litout; any-command) > /dev/ttyb"

Eckhard R"uggeberg


>From the stty man page:

DESCRIPTION stty sets certain terminal I/O options for the device that is the current standard output.

So, set the stdout *for the stty command* to the "arbitrary serial port." Eg, if dig_tty is set to the name of the port the digitizer is on (like /dev/ttya), then try "(stty -icrnl > $dig_tty)" where the parentheses mean execute in a subshell. You could also try

exec > $dig_tty stty -icrnl exec >/dev/tty


echo "stty -icrnl" | sh >$dig_tty.


Michael Fischbein, Dir. of Security Services, Fusion Systems Group. 24th Floor, 225 Broadway, New York, NY 1007


The usual trick is something like:

(stty -icrnl; sleep 1000000) > /dev/ttya

Modify as needed...

- Matt Goheen


Try using "stty -opost" when accessing the serial ports. This will prevent the line-feed to line-feed carrage-return convertion. Jeff Martin Aurora Technologies


The stty command in 4.1.x operates on stdout and prints information to stderr. Therefore, if you want to manipulate another port using stty, you can use something like

% stty erase ^R >/dev/ttyp2

Note that the change will only last for the current session, so once the tty is closed, it will revert to the default. Withing shell scripts, people usually do something like "sleep 1000000 </dev/ttyp2" in the background to keep the tty open, then kill that when they are done.

Also note that you can only do this if you have the necessary permissions for the /dev/tty* device.

Daniel Trinkle Dept. of Computer Sciences {backbone}!purdue!trinkle Purdue University 317-494-7844 West Lafayette, IN 47907-1398


This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:06:54 CDT