pseudo device driver (e.g. getting device driver-like behaviour from a userspace program


the pseudo device driver enters an infinite loop, creates a fifo for mkfifo /dev/pwm0; chmod a+w /dev/pwm0; to serial port action:
see Advanced Programming in the UNIX Environment, Addison-Wesley, 1992, ISBN 0-201-56317-7, by Richard Stevens.

to understand this code: man select

NAME
       select,  FD_CLR,  FD_ISSET,  FD_SET, FD_ZERO - synchronous
       I/O multiplexing
...
       int  select(int  n,  fd_set  *readfds,  fd_set  *writefds,
       fd_set *exceptfds, struct timeval *timeout);

       FD_CLR(int fd, fd_set *set);
       FD_ISSET(int fd, fd_set *set);
       FD_SET(int fd, fd_set *set);
       FD_ZERO(fd_set *set);

DESCRIPTION
       select  waits  for  a number of file descriptors to change status.
       Three independent sets of descriptors are watched.   Those
       listed  in  readfds  will  be watched to see if characters
       become available for reading (more precisely, to see if  a
       read  will not block - in particular, a file descriptor is
       also ready on end-of-file),  those  in  writefds  will  be
       watched  to  see  if  a write will not block, and those in
       exceptfds will be watched for exceptions.   On  exit,  the
       sets  are  modified in place to indicate which descriptors
       actually changed status.

Four macros are provided to manipulate the sets:
fd_set rfds; // globally defined structure for file descriptor select
int fd0;
int fd1;

int openfifo() {
  fd0 = open("/dev/pwm0", O_RDWR | O_SYNC); // open fifo for reading
  fd1 = open("/dev/pwm1", O_RDWR | O_SYNC);
  if( fd0 == -1 ) { perror("open");exit(1); }
  if( fd1 == -1 ) { perror("open");exit(1); }
...
int readfromfifo(int *whichservo) { // returns whichservo and value of servo
...
  FD_ZERO(&rfds);
  FD_SET(fd0, &rfds);
  FD_SET(fd1, &rfds);
  select( max(fd0, fd1)+1, &rfds, NULL, NULL, NULL);
...
  if (FD_ISSET(fd0, &rfds)) {
    read( fd0, &buffer, 1);
    *whichservo=0;
    printf("servo %d got some data\n", *whichservo);
}
  if (FD_ISSET(fd1, &rfds)) {
    read( fd1, &buffer, 1);
    *whichservo=1;
    printf("servo %d got some data\n", *whichservo);
  }
...
  // connect to the ssc
  if(ssc_open(port,baudrate)) perror("failed to open serial port");
  openfifo(); // global variable istead of return
  while (1) {
    x_in = readfromfifo(&servo); // servo number and x_in returned from function
...
    ssc_move( servo, x_in  );