[Previous]
[Contents]
[Next]

dev_read()

read data from a terminal device

Synopsis:

#include <sys/dev.h>
int dev_read( int fd,
              void *buf,
              unsigned n,
              unsigned min,
              unsigned time,
              unsigned timeout,
              pid_t proxy,
              int *armed );

Description:

The dev_read() function reads up to n bytes of data from the terminal device indicated by fd into the buffer pointed to by buf.

The dev_read() function is an alternative to the read() function for terminal devices. It provides additional arguments for timed read operations as well as arguments to control the triggering of proxies. These additional arguments can be used to minimize overhead when dealing with terminal devices.

The three arguments (min, time, and timeout), when used on terminal devices in RAW mode, override the behavior of the MIN and TIME elements of the currently defined termios structure (for the duration of this call only).

The following table describes the interaction of these three arguments:

min time timeout Description
0 0 0 Returns immediately with as many bytes as are currently available (up to n bytes).
M 0 0 Return with up to n bytes only when at least M bytes are available.
0 T 0 Return with up to n bytes when at least one byte is available, or T * .1 sec has expired.
M T 0 Return with up to n bytes when either M bytes are available, or at least one byte has been received and the inter-byte time between any subsequently received characters exceeds T * .1 sec.
0 0 t RESERVED
M 0 t Return with up to n bytes when t * .1 sec has expired, or M bytes are available.
0 T t RESERVED
M T t Return with up to n bytes when M bytes are available, or t * .1 sec has expired and no characters are received, or at least one byte has been received and the inter-byte time between any subsequently received characters exceeds T * .1 sec.

Note that when timeout is zero, the behavior of min and time is exactly the same as the behavior of the MIN and TIME parameters of the termios controlling structure. Thus, dev_read() can be used as a higher speed alternative to consecutive calls of tcgetattr(), tcsetattr(), and read() when dealing with RAW terminal I/O.

The (M, 0, t) case is useful for communications protocols that cannot afford to block forever waiting for data that may never arrive.

The (M, T, t) case is provided to permit dev_read() to return when a burst of data ends (as in the (M, T, 0) case), but also to return if no burst at all is detected within a reasonable amount of time.

The final two arguments (proxy and armed) allow dev_read() to be used in a nonblocking manner. Specifying a nonzero value for proxy causes dev_read() to return a zero and arm the proxy to be triggered in any situation where the read() call would have blocked.

If proxy is nonzero, and either the input conditions are not now satisfied (dev_read() returns zero), or this call has completely drained the input queue, the system arms this proxy to be triggered when the (M, T, t) input conditions are satisfied.

If the proxy is armed by the system, and the argument armed is nonzero, dev_read() sets the variable pointed to by armed.

If proxy is the bitwise complement of a signal number (that is, ~SIGXXX), that signal is generated on the calling process when data becomes available, rather than triggering a proxy. See <signal.h> for the list of signals.

Returns:

The number of bytes read. If an error occurs, dev_read() returns -1, and errno is set to indicate the error.

If proxy is nonzero, armed is nonzero if that proxy is armed as a result of the call.

Errors:

EAGAIN
The O_NONBLOCK flag is set on this fd, and the process would have been blocked in trying to perform this operation.
EBADF
The argument fd() is invalid or file is not opened for reading.
EINTR
The dev_read() call was interrupted by the process being signalled.
EIO
This process is not currently able to read data from this fd.
ENOSYS
This function is not supported for this fd.

Examples:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/dev.h>
#include <sys/proxy.h>
#include <sys/kernel.h>

unsigned char buf[100];

int main( void )
  {
    pid_t proxy, pid;
    int fd, armed, n, N = 10;

    fd = open( "/dev/ser1", O_RDONLY );
    /*
     * Read up to 'N' bytes from 'fd'
     * using (min, time, timeout) of (1, 0, 0)
     */
    n = dev_read( fd, buf, N, 1, 0, 0, 0, 0 );

    /*
     * The following example uses proxies to
     * kick us when data is available, allowing
     * the process to accept input from other tasks
     * (via messages) or from its input device,
     * without requiring polling.
     */

    proxy = qnx_proxy_attach( 0, 0, 0, -1 );

    /*
     * Arm the first proxy by reading zero bytes
     */
    n = dev_read( fd, buf, 0, 1, 0, 0, proxy, 0 );

    for( ;; ) {
      /*
       * wait for a proxy or message
       */
      pid = Receive( 0, buf, sizeof( buf ) );
      if( pid == proxy ) {
        armed = 0;
        while( !armed ) {
          /*
           * Continue processing data until exhausted
           */
          n = dev_read( fd, buf, N, 1, 0, 0,
                        proxy, &armed );
          /*
           * process 'n' bytes of data in 'buf'
           */
        }
      }
      else {
        /*
         * process other proxy or message from a task
         */
      }
    }
    return( EXIT_SUCCESS );
  }

Classification:

QNX

Safety:
Interrupt handler No
Signal handler Yes, but modifies errno
Thread Yes

Caveats:

Although this function is technically signal-handler- and thread-safe, it is context sensitive; for example, calling it from different threads with the same fd or proxy argument doesn't guarantee ordering.

See also:

dev_arm(), dev_state(), errno, read(), tcgetattr(), tcsetattr()


[Previous]
[Contents]
[Next]