//------------------------------------------------------------------- // nicasync.cpp // // This demo illustrates the use of asynchronous notification // to process packets received by the RealTek 8139 interface. // It relies upon a new version of our RealTek device-driver, // named 'nicasync.c', which implements the necessary support // for the asynchronous notification capability, as discussed // in the "Linux Device Drivers (3rd Ed)" book, in Chapter 6. // You can run our 'trychat.cpp' program from another station // on the local network in order to test this demo. // // compile with: $ g++ nicasync.cpp -o nicasync // // programmer: ALLAN CRUSE // written on: 27 APR 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), write(), close() #include // for strlen() #include // for sigaction() #include // for fcntl() #include // for wait() #include // for POLLIN, POLLOUT #include // for htons() #define CHAT_ID 0x0635 // identifies our packet-protocol int done = 0; char devname[] = "/dev/nic"; void my_sigaction( int signo, siginfo_t *info, void *data ) { if ( signo == SIGINT ) done = 1; // -C pressed else if ( signo != SIGUSR1 ) return; // validate signal-information: data is ready to be read if ( info->si_code != 1 ) return; if ( (info->si_band & POLL_IN)==0 ) return; // read the new data from the network device unsigned char msg[ 1536 ] = {0}; if ( read( info->si_fd, msg, sizeof( msg ) ) < 0 ) return; // if it's a 'netchat' packet, then display its character if ( *(short*)(msg+12) == htons( CHAT_ID ) ) { int nbytes = *(short*)(msg+14); write( STDOUT_FILENO, msg+16, nbytes ); } } int main( void ) { // install our signal-handler struct sigaction oa, sa = {0}; sigset_t my_mask; sigemptyset( &my_mask ); // no blocked signals sa.sa_sigaction = my_sigaction; sa.sa_mask = my_mask; sa.sa_flags = SA_SIGINFO; sigaction( SIGUSR1, &sa, &oa ); sigaction( SIGINT, &sa, NULL ); // open the device-file int fd = open( devname, O_RDWR ); if ( fd < 0 ) { perror( devname ); exit(1); } // set device-file's owner (for signal-delivery) fcntl( fd, F_SETOWN, getpid() ); // specify which signal is to be delivered fcntl( fd, F_SETSIG, SIGUSR1 ); // enable asynchronous notification int flags = fcntl( fd, F_GETFL ); fcntl( fd, F_SETFL, flags | FASYNC ); // main loop to await -C typed by user while ( !done ) pause(); // restore the original signal-handler for SIGUSR1 sigaction( SIGUSR1, &oa, NULL ); // close the device-file and terminate this program close( fd ); exit(0); }