![]() |
Using Linux to Send Commands to ADR Interfaces This page will demonstrate how to send and receive data from the ADR112 or any other ADR interface, using Linux gcc programmes. It shows the commands used to configure the serial port, send data out through the serial port, and receive data through the serial port. Additional help is available from the Linux HowTo documents found at a variety of locations around the web (hint: use a search engine). The man pages of your Linux system are invaluable as well. I make no effort to explain all of the parameters used in the various API calls. Read The Famous Manual. This page is divided into several sections. The first section presents the source code with brief usage details. The second section shows pictorial examples and screen shots. Some troubleshooting hints are given in the second section. The third section describes some details (skip it if the first two sections provide what you need.) Linux VersionI tested this program using Redhat 7.3, however I believe this code will operate correctly under all recent Linux kernels (your mileage may vary). The code was compiled with version 2.96-110 of the gcc compiler. Any recent vintage of the gcc compiler should be fine. Source CodeThere are four files needed to compile the Linux example.
adrport.h
// adrport.h
// Copyright MMI, MMII by Sisusypro Incorporated
int OpenAdrPort (char* sPortNumber);
int WriteAdrPort(char* psOutput);
int ReadAdrPort(char* psResponse, int iMax);
void CloseAdrPort();
adrport.c
// adrport.c - Serial Port Handler
// Copyright MMI, MMII by Sisusypro Incorporated
// Permission is hereby granted to freely copy,
// modify, utilize and distribute this example in
// whatever manner you desire without restriction.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include "adrport.h"
static int fd = 0;
// opens the serial port
// return code:
// > 0 = fd for the port
// -1 = open failed
int OpenAdrPort(char* sPortNumber)
{
char sPortName[64];
printf("in OpenAdrPort port#=%s\n", sPortNumber);
sprintf(sPortName, "/dev/ttyS%s", sPortNumber);
printf("sPortName=%s\n", sPortName);
// make sure port is closed
CloseAdrPort(fd);
fd = open(sPortName, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0)
{
printf("open error %d %s\n", errno, strerror(errno));
}
else
{
struct termios my_termios;
printf("fd is %d\n", fd);
tcgetattr(fd, &my_termios);
// NOTE: you may want to save the port attributes
// here so that you can restore them later
printf("old cflag=%08x\n", my_termios.c_cflag);
printf("old oflag=%08x\n", my_termios.c_oflag);
printf("old iflag=%08x\n", my_termios.c_iflag);
printf("old lflag=%08x\n", my_termios.c_lflag);
printf("old line=%02x\n", my_termios.c_line);
tcflush(fd, TCIFLUSH);
my_termios.c_cflag = B9600 | CS8 |CREAD | CLOCAL | HUPCL;
cfsetospeed(&my_termios, B9600);
tcsetattr(fd, TCSANOW, &my_termios);
printf("new cflag=%08x\n", my_termios.c_cflag);
printf("new oflag=%08x\n", my_termios.c_oflag);
printf("new iflag=%08x\n", my_termios.c_iflag);
printf("new lflag=%08x\n", my_termios.c_lflag);
printf("new line=%02x\n", my_termios.c_line);
} // end if
return fd;
} // end OpenAdrPort
// writes zero terminated string to the serial port
// return code:
// >= 0 = number of characters written
// -1 = write failed
int WriteAdrPort(char* psOutput)
{
int iOut;
if (fd < 1)
{
printf(" port is not open\n");
return -1;
} // end if
iOut = write(fd, psOutput, strlen(psOutput));
if (iOut < 0)
{
printf("write error %d %s\n", errno, strerror(errno));
}
else
{
printf("wrote %d chars: %s\n", iOut, psOutput);
} // end if
return iOut;
} // end WriteAdrPort
// read string from the serial port
// return code:
// >= 0 = number of characters read
// -1 = read failed
int ReadAdrPort(char* psResponse, int iMax)
{
int iIn;
printf("in ReadAdrPort iMax=%d\n", iMax);
if (fd < 1)
{
printf(" port is not open\n");
return -1;
} // end if
strncpy (psResponse, "N/A", iMax<4?iMax:4);
iIn = read(fd, psResponse, iMax-1);
if (iIn < 0)
{
if (errno == EAGAIN)
{
return 0; // assume that command generated no response
}
else
{
printf("read error %d %s\n", errno, strerror(errno));
} // end if
}
else
{
psResponse[iIn<iMax?iIn:iMax] = '\0';
printf("read %d chars: %s\n", iIn, psResponse);
} // end if
return iIn;
} // end ReadAdrPort
// closes the serial port
void CloseAdrPort()
{
// you may want to restore the saved port attributes
if (fd > 0)
{
close(fd);
} // end if
} // end CloseAdrPort
adrserial.c
// adrserial.c - Serial Port Test Example
// Copyright MMII by Sisusypro Incorporated
// WARNING: Example only. Lacks error checking!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "adrport.h"
// this is the mainline thingee
int main(int argc, char *argv[])
{
char sCmd[254];
char sResult[254];
if (argc < 2 || argc > 2)
{
printf("adrserial needs 1 parameter for the serial port\n");
printf(" ie. use 'adrserial 0' to connect to /dev/ttyS0\n");
return 0;
} // end if
printf("Type q to quit.\n\n");
if (OpenAdrPort(argv[1]) < 0) return 0;
while (1)
{
int iSpot;
printf("?:");
gets(sCmd);
if (sCmd[0] == 'q' || sCmd[0] == 'Q') return 0;
iSpot = strlen(sCmd);
sCmd[iSpot] = 0x0d; // stick a <CR> after the command
sCmd[iSpot+1] = 0x00; // terminate the string properly
if (WriteAdrPort(sCmd) < 0) return 0;
sleep(1); // give the ADR card some time to respond
if (ReadAdrPort(sResult,254) > 0)
{
printf("****Response is %s\n", sResult);
} // end if
} // end while
CloseAdrPort();
} // end main
Makefile
CFLAGS=-g -Wall
adrserial: adrserial.c adrport.c
gcc -g -c -Wall adrserial.c -o adrserial.o
gcc -g -c -Wall adrport.c -o adrport.o
gcc adrport.o adrserial.o -o adrserial
Ontrak will send you a tarred and gzipped version of the above files (see bottom of this page), but it includes nothing beyond what is listed above. Building the Linux Example
Running the adrserial ExamplePermissionsFirst off, you have to grant permission to access the serial port. On my system I
logged in with root authority and used chmod to grant all users read/write access to the
serial port.
chmod o+rw /dev/ttyS0
The adrserial programme has a single parameter: the numeric value
for the selected serial port. On my system the ADR card is connected to the first serial
port which is known as /dev/ttyS0 in Linux. (please adjust the following instructions to
match your system.) Here is the ADR112 card that I used to test this programme. Here is a screen-shot of the adrserial programme starting up. followed by a number of lines of debug information. The ?: is a prompt to enter a
command for the ADR112. Here is a screen-shot of 2 ADR commands. After these two commands the LED connected to PA1 is lit up. The rpa command instructs the ADR card to report the status of all 8 lines on PortA. Prior to the next command I used the red wire to feed +5 volts to PA7. This caused the
LED on PA7 to light up. An rpa command was sent to the ADR card eliciting the following response. The remainder of this page contains some additional details that you may skip at your
discretion. Some of this is directed at Linux newbies. Do not call Ontrak and for help about this example. It is provided as a courtesy to
show the operation of an ADR card in the Linux environment. It is not supported. All the screen-shots show an xterm session running on a Gnome desktop. The caption bar
shows the userid, jhomppi, and the machine name, guardian. (This machine normally operates
as an Internet firewall.... hence guardian is its name). The shell prompt is the userid followed by the directory in which the example resides: The current directory (ie dot) is not in the path. Thus it must be specified in the
command to start the programme: The programme can be run from a normal tty console session (ie. command line). You do
not need to start an xterm. You do not need to start the x-window environment. When you have a numeric error code you will find that all of the man pages refer to
#defined constants (eg EAGAIN). The /usr/include header files help you translate an error
number into its constant. On our development system (Redhat Linux 7.3) the file /usr/include/asm/errno.h contains
a long list of defined error constants. Looking up the EAGAIN constant shows a value of
11. Searching For Error Codes. You can use the "find" and "grep"
commands to locate all the headers referring to a given defined constant. For example, the
header files that refer to the EAGAIN constant can be listed with the following command: This example is based on information gleaned from many Internet Web sites. Special
accolades go to the following. This programme is free. Free of cost. Free of restrictions. You can use it, copy it,
modify it, distribute it and include it in your own application programme. I hope this assists your programming efforts. John Homppi To retrieve the Linux files used in this example (200K ) in ZIP
format, click "LINUX
EXAMPLE" After you receive the LinuxEg.tar.gz file you must decompress it with: and then untar it with: |
|