Re: [PATCH 001/001] CHAR DRIVERS: a simple device to give daemons a /sys-like interface

Bob Smith
2013-08-07T19:02:08Z

Greg
This sample program shows what I'm trying to accomplish.

I still owe you a reply for your previous posting

thanks
Bob Smith

/*
* pxtest.c : This program demonstrates the use of a proxy device.
*
* The program generates some data once a second and tries to send
* it to /dev/proxyout. The original data is modified by adding
* an offset to each input character. The offset can be set or
* viewed at the proxy device node /dev/proxyctrl.
*
* Typical usage might be
* sudo modprobe proxy
* PROXYDEV=`grep proxy /proc/devices | cut -d\ -f 1`
* sudo mknod /dev/proxyout c $PROXYDEV 0
* sudo mknod /dev/proxyctrl c $PROXYDEV 1
* sudo chmod 666 /dev/proxyout /dev/proxyctrl
* gcc -o pxtest pxtest.c
* ./pxtest &
* cat /dev/proxyout # view the output
* (switch to another terminal window)
* cat /dev/proxyctrl # what is the offset?
* echo 2 > /dev/proxyctrl # set offset to 2
*/

#include <stdio.h>
#include <stdlib.h>
#include <termio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/time.h>

extern int errno;
#define PXBUFZS 100

int main (int argc, char *argv[])
{
fd_set rfds; /* for select() */
fd_set wfds; /* for select() */
int nfds; /* for select() */
struct timeval tv; /* for select() */
time_t now; /* source of input data */
int i;
int offset = 0; /* configured via /dev/proxyctrl */
int outfd; /* fd to /dev/proxyout */
char obuff[PXBUFZS];
int listener; /* ==1 if someone is listening at /dev/proxyout */
int ctrlfd = -1; /* fd to /dev/proxyctrl */
char cbuff[PXBUFZS]; /* i/o buffer for /dev/proxyctrl */
int slret,wrret,rdret; /* select() write() read() return value */

outfd = open("/dev/proxyout", (O_WRONLY | O_NDELAY) , 0);
if (outfd < 0 ) {
printf("Unable to open proxy output port\n");
exit(1);
}
listener = 0;

tv.tv_sec = 1;
tv.tv_usec = 0;

while(1) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);

/* open, or reopen, the offset control port at /dev/proxyctrl */
if (ctrlfd == -1) {
ctrlfd = open("/dev/proxyctrl", O_RDWR | O_NDELAY,0);
if (ctrlfd < 0 ) {
printf("Unable to open proxy control port\n");
exit(1);
}
}
FD_SET(ctrlfd, &rfds);
FD_SET(ctrlfd, &wfds);

/* If no one is listening, watch for a connection */
if (listener == 0) {
FD_SET(outfd, &wfds);
}

nfds = (outfd > ctrlfd) ? outfd : ctrlfd;

slret = select((nfds + 1), &rfds, &wfds, (fd_set *)NULL, &tv);

if (slret == 0) {
/* Generate bogus data. Real data might be coming from
* an I2C read or from an accelerometer at the end of a
* USB serial link. For now, just use the current time */
time(&now);
ctime_r(&now, obuff);

/* "process" the data by adding offset to each character */
i = 0;
while (obuff[i] != '\n') {
obuff[i] = (char) (obuff[i] + offset);
obuff[i] = (isprint(obuff[i])) ? obuff[i] : '_';
i++;
}

/* Try to send the processed output to /dev/proxyout if possible */
if (listener == 1) {
wrret = write(outfd, obuff, strlen(obuff));
if ((wrret == 0) || ((wrret < 0) && (errno == EAGAIN))) {
/* listener dropped off */
listener = 0;
}
}
tv.tv_sec = 1;
tv.tv_usec = 0;
}

/* Did a listener attach at /dev/proxyout? */
if (FD_ISSET(outfd, &wfds)) {
listener = 1;
}

/* Data on /dev/proxyctrl is marshalled as newline terminated ASCII
* This is not a requirement. Use binary, XML or whatever you need.
* This demo forces a close but that too is not required. */

/* Did anyone ask to read the offset value? */
if (FD_ISSET(ctrlfd, &wfds)) {
snprintf(cbuff, PXBUFZS, "%d\n", offset);
write(ctrlfd, cbuff, strlen(cbuff)); /* send offset value */
write(ctrlfd, cbuff, 0); /* send EOF */
}

/* Is anyone trying to set the offset value? */
if (FD_ISSET(ctrlfd, &rfds)) {
rdret = read(ctrlfd, cbuff, PXBUFZS);
if (rdret == 0) {
close(ctrlfd);
ctrlfd = -1;
} else if ((rdret > 0) && (cbuff[rdret - 1] == '\n')) {
/* buffer mgmt should be more than checking for ending \n */
sscanf(cbuff, "%d", &offset);
}
}
}
}