7.4 Command and Event Processing

(Page 5 of 11 in this chapter)
This section describes the command and event mechanism within AG Access. Figure 32 is a block diagram depicting the interaction between the application program and AG Access components. In the figure, circled numbers are sequences in the command path and triangle numbers are sequences in the event path.

The interchange between the different components is described following the diagram.



: Command and Event Processing Block Diagram

Commands are processed in the downward direction from the application program to the AG board. AG Access commands are processed in the following sequence:

  1. The application invokes an AG Access function and supplies a port handle (porthd).

  2. AG Access modifies the internal port context when processing the command.

  3. AG Access maps the port handle to the driver handle and delivers the command to the AG driver.

  4. The AG driver delivers the command to the port's AG board.

Events are processed in the upward direction from the AG board to the application program. AG Access events are processed in the following sequence:

  1. The application invokes an OS-specific wait routine.

  2. The AG driver signals the application process that the driver needs servicing.

  3. The application invokes adiFetchAndProcess, passing the driver handle.

  4. AG Access reads the event from the driver into the application's data space.

  5. AG Access maps the event to a port and modifies the port context when processing the event.

  6. If an event needs to be delivered to the application program, adiFetchAndProcess assigns the application-supplied event structure.

The AG driver awakens the application process by "posting" to the driver mux handle returned from adiOpenDriver. The mux handle is operating system dependent and is used in the following way:

Example

/*
 * This function blocks until an event message is available
 * and returns the received event to the calling routine.
 *  MUX_HANDLE is typedef'd in adidef.h for portability.
 */
void myWaitForEvent( unsigned drvid, 
                     MUX_HANDLE muxhandle,
                     ADI_EVENT *event )
    {
    ...
    /*
     *  adiFetchAndProcess() assigns a non-zero event id
     *  when an event is generated for the app.
     */
    event->id = 0 ;

    while( event->id == 0 )
        {
#ifdef UNIX
        struct pollfd fds[1];
        fds[0].events = POLLIN;
        fds[0].fd     = muxhandle;

        if (  poll( fds, 1, -1 ) < 0 )
            {
            if ( errno == EINTR )
                continue ;
            perror("poll") ;
            exit( 1 );
            }
#elif defined OS2
        APIRET ret;
        if( ( ret = (int)DosWaitEventSem( muxhandle,
                    (unsigned)SEM_INDEFINITE_WAIT ) ) != 0 )
            {
            printf( "Error on DosWaitEventSem: %d\n", ret );
            exit( 1 );
            }
#elif defined WIN32
        if( WaitForSingleObject( muxhandle, INFINITE ) 
                                        ==WAIT_FAILED )
            {
            printf( "Error on WaitForSingleObject: %d\n",
                     GetLastError() );
            exit( 1 );
            }
#endif

        /* 
         * Allow ADI to fetch the event and process it through its
         * internal state machine.
         */
        adiFetchAndProcess( drvid, event );
        }

    return;
    }

7.4.1 Unix Signals

Unix applications may use the SIGPOLL signal to be notified when the AG driver requires processing. This allows AG events to be processed asynchronously from the main() routine.

CAUTION: The AG Access library is not reentrant with respect to Unix signal handlers. If using a signal handler to process AG events, you must block the SIGPOLL signal before invoking any AG Access library functions.

The application must perform a two-step process in order to use the signal handling mechanism:

  1. Define the SIGPOLL signal's disposition and instruct the kernel to deliver a SIGPOLL signal when AG driver input is ready.

  2. Write a signal handler to service the AG driver when the SIGPOLL is delivered.

The following configures the kernel to invoke a signal handler when SIGPOLL is delivered.

        unsigned driver_id ;    /* global variable -- see signal handler */
        struct sigaction sigact = 
        {
            0,
            MySignalHandler, 
            0 
        };
        adiOpenDriver( &driver_id, &muxhandle );
         if ( sigaction( SIGPOLL, &sigact, NULL ) != 0 ) 
             perror("sigaction");
         if ( ioctl( muxhandle, I_SETSIG, S_RDNORM ) != 0 )
             perror("ioctl");
Note: The ioctl flags must be set to S_RDNORM.

The following sample signal handler reads events from AG Access and processes them until there are no more events in the AG driver.

         void MySignalHandler() 
         { 
             ADI_EVENT adi_event ;
             DWORD     adiret ; 
             do  
              { 
                 adiret = adiFetchAndProcess( driver_id, &adi_event ); 
                 if ( adiret == SUCCESS )  
                     /* process event */ 
               } until ( adiret == ADIERR_RECEIVE_FAILED ) ; 
         }
Note: The signal handler must invoke adiFetchAndProcess until there are no more AG driver events queued in the STREAM head.


(Page 5 of 11 in this chapter)

Copyright 1996 Natural MicroSystems, Inc. All Rights Reserved.