How to set/read serial device pins directly

How to set/read serial device pins directly

Post by Camiel Rouwele » Sat, 24 Jun 2000 04:00:00



I have to do the following task: determine the state of a certain switch,
which is connected to a serial port. It is specified that if I set a high
signal to the RTS pin, that I can read the state of the switch (on or off)
on the CTS pin.

How do I do this? I have no clue how to control the serial port and all the
documentation I have found so far seems to deal only with communication of
entire characters through the serial port and not with controlling single
pins.

If anyone could give me some hints or point me to a useful FAQ, I would be
very happy.

If possible, could you please also send a reply by e-mail?

Thanks,

Camiel Rouweler

 
 
 

How to set/read serial device pins directly

Post by Alexander Soliani » Sat, 24 Jun 2000 04:00:00


man termio, termios

--


.com...

Quote:> I have to do the following task: determine the state of a certain switch,
> which is connected to a serial port. It is specified that if I set a high
> signal to the RTS pin, that I can read the state of the switch (on or off)
> on the CTS pin.

> How do I do this? I have no clue how to control the serial port and all
the
> documentation I have found so far seems to deal only with communication of
> entire characters through the serial port and not with controlling single
> pins.

> If anyone could give me some hints or point me to a useful FAQ, I would be
> very happy.

> If possible, could you please also send a reply by e-mail?

> Thanks,

> Camiel Rouweler


 
 
 

How to set/read serial device pins directly

Post by Floyd Davidso » Sat, 24 Jun 2000 04:00:00


"Alexander Solianic" <solia...@null.ru> wrote:
>man termio, termios

That will not be much help for any termios man page I've ever
read.

>"Camiel Rouweler" <camiel.rouwe...@asml.nl> wrote:
>> I have to do the following task: determine the state of a
>> certain switch, which is connected to a serial port. It is
>> specified that if I set a high signal to the RTS pin, that I
>> can read the state of the switch (on or off) on the CTS pin.

>> How do I do this? I have no clue how to control the serial
>> port and all the documentation I have found so far seems to
>> deal only with communication of entire characters through the
>> serial port and not with controlling single pins.

>> If anyone could give me some hints or point me to a useful
>> FAQ, I would be very happy.

It might vary considerably depending on the specific UNIX being
used.  The best bet is to fetch the source code to two or three
modem programs that are known to work on that platform, and look
to see how it those programs managed to handle RTS and CTS.
(minicom, seyon, pcomm, pppd etc are all helpful.)

Here is an example, which works on Linux.  I am assuming that
there might also be a need to know how to check status of the
DCD (Carrier Detect) line, because if said device is cabled
correctly the DCD line will only be set when the device is
actually connected.  Otherwise it is impossible to differentiate
between CTS off and loose cable connectors breaking the
connection.

This demo only checks the status, of a variety of things though,
most of which are probably not important in this specific
application but are included just in case they are interesting.
At the end of the code are a couple functions which can be used
to set or clear modem control lines.  Hints are included about
some of the possible variations that might be encountered on
different platforms.

  Floyd

/*
 *  Serial.c  --  demonstrates how to diddle with modem control lines.
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <linux/serial.h>
#include <sys/ioctl.h>

void show_serial(char *);

/*
 * list of serial ports this program checks
 */
#define MAXDEVICES 4
char devices[MAXDEVICES][30] = {
  "/dev/ttyS0",
  "/dev/ttyS1",
  "/dev/ttyS2",
  "/dev/ttyS3"

};

int
main(void)
{
  int i;

  for (i = 0; i < MAXDEVICES; ++i) {
    show_serial(devices[i]);
  }

  return EXIT_SUCCESS;

}

#if 0
/*
 *  These lists are from /usr/include/asm/termios.h on a Linux box.
 *  They might be different on other platforms, and are included here
 *  for instructional purposes only.
 */

/* line disciplines */
#define N_TTY           0
#define N_SLIP          1
#define N_MOUSE         2
#define N_PPP           3
#define N_STRIP         4
#define N_AX25          5
#define N_X25           6       /* X.25 async */
#define N_6PACK         7
#define N_MASC          8       /* Reserved for Mob ... [snipped] */
#define N_R3964         9       /* Reserved for Sim ... [snipped] */
#define N_PROFIBUS_FDL  10      /* Reserved for Pro ... [snipped] */
#define N_IRDA          11      /* Linux IR - http: ... [snipped] */
#define N_SMSBLOCK      12      /* SMS block mode - ... [snipped] */
#define N_HDLC          13      /* synchronous HDLC */

/* modem lines */
#define TIOCM_LE        0x001
#define TIOCM_DTR       0x002
#define TIOCM_RTS       0x004
#define TIOCM_ST        0x008
#define TIOCM_SR        0x010
#define TIOCM_CTS       0x020
#define TIOCM_CAR       0x040
#define TIOCM_RNG       0x080
#define TIOCM_DSR       0x100
#define TIOCM_CD        TIOCM_CAR
#define TIOCM_RI        TIOCM_RNG
#define TIOCM_OUT1      0x2000
#define TIOCM_OUT2      0x4000

#endif

void show_serial(char *device) {
  int                  valid;
  int                  rts;
  int                  openflag;
  int                  cntrlreg;
  int                  fd;
  int                  results;
  struct termios       term;
  struct serial_struct serinfo; /* defined in /usr/include/asm/serial.h */

  valid    = 1;
  openflag = 0;

  if ((fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0) {
    valid    = 0;
    printf("Device:  %s  <Cannot be opened>", device);
  } else {
    openflag = 1;
  }

  serinfo.reserved_char[0] = 0;

  if (valid && ioctl(fd, TIOCGSERIAL, &serinfo) < 0) {
    valid = 0;     /* can't get serial info */
    printf("Device:  %s  <cannot get serial info struct>", device);
  }

  if (valid && ioctl(fd, TIOCMGET, &cntrlreg) < 0) {
    valid = 0;     /* can't get control register */
    printf("Device:  %s  <cannot get control register>", device);
  }

  if (serinfo.line >= MAXDEVICES) {
    valid = 0;    /* out of interesting range */
    printf("Device:  %s  <Device is out of range>", device);
  }

  if (valid) {
    printf("device:  %s:  DCD = %s",
           device,
           cntrlreg & TIOCM_CAR ? "ON" : "OFF");
  }

#if 0
  if (! (cntrlreg & TIOCM_CAR)) {
    valid = 0;    /* no carrier detect */
  }
#endif

  if (valid && tcgetattr(fd, &term) < 0) {
    valid = 0;    /* can't get termios info */
    printf("  <Cannot get termios struct> ", device);
  }

  if (valid && B0 == cfgetospeed(&term)) {
    valid = 0;   /* disabled if speed is 0 */
    printf("  [Speed is set to 0 (DTR cleared)] ", device);
  }

  if( valid && ioctl (fd, TIOCSERGETLSR, &results) < 0) {
    valid = 0;   /* can't check line status */
    printf("  <Cannot get line status register> ", device);
  }

  if (valid &&
      results &&
      term.c_line != N_SLIP &&
      term.c_line != N_PPP &&
      term.c_line != N_TTY) {
    valid = 0;   /* not a tty, ppp orb slip line */
    printf("  [Not set for tty, slip or ppp line discipline] ", device);
  }

  rts = !(cntrlreg & TIOCM_RTS);

  if (valid) {
    printf("  rcs status:  %s", rts ? "ON" : "OFF");

  }

  if (openflag) {
    close(fd);
  }

  putchar('\n');

  return;

}  

#if 0

/*
 * Two different ways to set/clear modem control lines.
 */

/*
 *   Set or Clear DTR modem control line
 *
 *   Note:  TIOCMBIS:   CoMmandd bIt Set
 *          TIOCMBIC:   CoMmandd bIt Clear
 *
 */
void
setdtr (int fd, int on)
{
    int controlbits = TIOCM_DTR;
    ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &controlbits);

}

/*
 *   Set or Clear RTS modem control line
 *
 *   Note:  TIOCMSET and TIOCMGET are POSIX
 *
 *          the same things:
 *
 *          TIOCMODS and TIOCMODG are BSD (4.3 ??)
 *          MCSETA and MCGETA are HPUX
 */
void
setrts(int fd, int on)
{
  int controlbits;

  ioctl(fd, TIOCMGET, &controlbits);
  if (on) {
    controlbits |=  TIOCM_RTS;
  } else {
    controlbits &= ~TIOCM_RTS;
  }
  ioctl(fd, TIOCMSET, &controlbits);

}

#endif