📄 dttty.c
字号:
/**************************************************************************** * * * COPYRIGHT (c) 1990 - 2004 * * This Software Provided * * By * * Robin's Nest Software Inc. * * * * Permission to use, copy, modify, distribute and sell this software and * * its documentation for any purpose and without fee is hereby granted, * * provided that the above copyright notice appear in all copies and that * * both that copyright notice and this permission notice appear in the * * supporting documentation, and that the name of the author not be used * * in advertising or publicity pertaining to distribution of the software * * without specific, written prior permission. * * * * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * * NO EVENT SHALL HE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL * * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF * * THIS SOFTWARE. * * * ****************************************************************************//* * Module: dttty.c * Author: Robin T. Miller * * Description: * Terminal line support functions for generic data test program. */#include "dt.h"#include <fcntl.h>#if !defined(_QNX_SOURCE)# if !defined(sun)# include <sys/ioctl.h># endif /* !defined(sun) */# include <sys/file.h># include <sys/param.h>#endif /* !defined(_QNX_SOURCE) *//* * Define maximum values for VMIN & VTIME field values: */#if defined(_QNX_SOURCE)# define VMIN_MAX 65535U# define VTIME_MAX 65535U#else /* !defined(_QNX_SOURCE) */# define VMIN_MAX 255U# define VTIME_MAX 255U#endif /* defined(_QNX_SOURCE) *//* * Modification History: * * November 17th, 2003 by Robin Miller. * Breakup output to stdout or stderr, rather than writing * all output to stderr. If output file is stdout ('-') or a log * file is specified, then all output reverts to stderr. * * September 27th, 2003 by Robin Miller. * Added support for AIX. * * February 23rd, 2002 by Robin Miller. * Make porting changes for HP-UX IA64. * * December 30th, 2000 by Robin Miller. * Make changes to build using MKS/NuTCracker product. * * May 8th, 2000 by Robin Miller. * Honor the di_closing flag, to avoid a race condition with the * close function being called again while still closing, from the * terminate() routine called by the runtime= alarm, or signals. * * February 17th, 2000 by Robin Miller. * Adding better support for multi-volume tape testing. * * July 29, 1999 by Robin Miller. * Merge in changes made to compile on FreeBSD. * * May 27, 1999 by Robin Miller. * Adding support for micro-second delays. * * December 19, 1995 by Robin Miller * Conditionalize for Linux Operating System. * * December 7, 1995 by Robin Miller. * Conditionally support speeds of 38400, 57600, 76800, & 115200. * * December 6, 1995 by Robin Miller. * When setting the VMIN and VTIME, ensure the maximum values are * not exceeded or blindly truncated to an incorrect value. These * fields are currently declared as unsigned char's, so 255 is the * maximum value possible. [ I've been burnt by this too... ] * Added additional baud rates supported by QNX Operating System. * * July 24, 1995 by Robin Miller. * When doing modem testing, after waiting for carrier, disable * non-blocking mode, to prevent EWOULDBLOCK on reads & writes. * [ We open'ed w/O_NONBLOCK so we could read modem signals. ] * * October 29, 1993 by Robin Miller. * Add test in tty_open() to ensure the terminal characteristics * only get saved once when performing loopback to same terminal. * Otherwise test attributes get restored, instead of original. * * September 7, 1993 by Robin Miller. * Added tty specific test functions & test function dispatch table. * * September 24, 1992 by Robin Miller. * If parity is being enabled, ensure input parity checking is also * enabled, since these are independent of each other. This change * will allow parity and framing errors to come back as '\0' in the * input stream, instead of silently being ignored. * * September 19, 1992 by Robin Miller. * Added flushing of tty input & output queue in save_tty() to * prevent unwarrented data comparison errors during testing. * * September 18, 1992 by Robin Miller. * Added save_tty() & restore_tty() routines to save & restore the * terminal line discipline and characteristics. This must be done * since other programs may presume a certain tty setup. * * September 11, 1992 by Robin Miller. * Change 3rd parmameter of TCBRK ioctl() to -1 instead of 1, to * inhibit sending of actual break sequence and only drain output. * This caused 'dt' to get intermittent data compare errors (ouch!). * * September 5, 1992 by Robin Miller. * Initial port to QNX 4.1 Operating System. * * August 19, 1992 by Robin Miller. * Added modem support functions and modem test setup. * * August 18, 1992 by Robin Miller. * Added support for ULTRIX terminal driver setup (yuck!). * Also ensure tty line discipline is setup properly. * * June 5, 1992 by Robin Miller. * Added setting the terminal attributes for 2 stop bits for * baud rates slower than 300 baud. * * May 25, 1992 by Robin Miller. * Added POSIX compliant tty commands for OSF terminal driver. * Ensure CLOCAL & HUPCL do not get cleared inadvertantly. * * October 16, 1989 by Robin Miller. * Added setting the ISTRIP terminal characteristic when testing * with even or odd parity. This is needed for Sun's zs driver * which passes the parity bit through if this isn't set, even * though we have setup for only 7 data bits (SUN's bug). * * July 25, 1989 by Robin Miller. * Add functions for setting up terminal chacteristics for testing * terminal ports in loopback mode. * */#if defined(__WIN32__) && !defined(__NUTC__)extern int tcgetattr(int , struct termios *);extern int tcsetattr(int , int , const struct termios *);extern int tcsendbreak(int , int );extern int tcdrain(int );extern int tcflush(int , int );extern int tcflow(int , int );#endif /* defined(__WIN32__) && !defined(__NUTC__) *//* * Table to Map Baudrate to tty Speed Codes. */struct tty_baud_rate baud_rate_tbl[] = { { 0, B0 }, { 50, B50 }, { 75, B75 }, { 110, B110 }, { 134, B134 }, { 150, B150 }, { 200, B200 }, { 300, B300 }, { 600, B600 }, { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 },#if defined(B38400) { 38400, B38400 },#endif /* defined(B38400) */#if defined(B57600) { 57600, B57600 },#endif /* defined(B57600) */#if defined(B76800) { 76800, B76800 },#endif /* defined(B76800) */#if defined(B115200) { 115200, B115200 },#endif /* defined(B115200) */ { 0, 0 }};int num_baud_rates = (sizeof(baud_rate_tbl) / sizeof(baud_rate_tbl[0])) - 1;char *parity_str = "none";char *flow_str = "xon_xoff";char *speed_str = "9600";speed_t baud_rate_code = B9600; /* Default baud rate is 9600. */unsigned parity_code = 0; /* Default parity = none. */unsigned data_bits_code = CS8; /* Default data bits = 8. */bool tty_saved; /* tty characteristics saved. */int saved_ldisc; /* For saving line discipline. */struct termios saved_tmodes; /* For saving terminal modes. *//* * Declare the terminal test functions. */struct dtfuncs tty_funcs = { /* tf_open, tf_close, tf_initialize, */ tty_open, tty_close, initialize, /* tf_start_test, tf_end_test, */ nofunc, nofunc, /* tf_read_file, tf_read_data, tf_cancel_reads, */ read_file, read_data, nofunc, /* tf_write_file, tf_write_data, tf_cancel_writes, */ write_file, write_data, nofunc, /* tf_flush_data, tf_verify_data, tf_reopen_file, */ tty_flush_data, verify_data, tty_reopen, /* tf_startup, tf_cleanup, tf_validate_opts */ nofunc, nofunc, validate_opts};/************************************************************************ * * * tty_open() - Open a terminal device for read/write access. * * * * Description: * * This function does the terminal device open processing. * * * * Inputs: dip = The device information pointer. * * oflags = The device/file open flags. * * * * Return Value: * * Returns 0 / -1 = SUCCESS / FAILURE. * * * ************************************************************************/inttty_open (struct dinfo *dip, int oflags){ int status; if ((status = open_file (dip, oflags)) == FAILURE) { return (status); }#if !defined(_QNX_SOURCE) && !defined(sun) && !defined(__MSDOS__) && !defined(__WIN32__) && !defined(HP_UX) if (!debug_flag && !loopback) { if ((status = ioctl (dip->di_fd, TIOCEXCL, 0)) == FAILURE) { report_error ("TIOCEXCL", FALSE); return (status); } }#endif /* !defined(_QNX_SOURCE) */ /* * Setup & optionally flush the input queue. */ if (dip->di_mode == READ_MODE) { if ((status = save_tty (dip->di_fd)) < 0) return (status); if ((status = flush_tty (dip->di_fd)) < 0) return (status); } else if (!loopback) { /* * If looping to ourselves, setup is already done above. * [ Presumes input file opened before the output file. ] */ if ((status = save_tty (dip->di_fd)) < 0) return (status); if ((status = setup_tty (dip->di_fd, FALSE)) < 0) return (status); } verify_flag = FALSE; if ((dip->di_ftype == OUTPUT_FILE) && !loopback && (sdelay_count == 0)) { sdelay_count = 1; /* Delay before write on tty. */ } return (status);}/************************************************************************ * * * tty_close() - Close a terminal device file descriptor. * * * * Description: * * This function does the terminal device close processing. * * * * Inputs: dip = The device information pointer. * * * * Return Value: * * Returns 0 / -1 = SUCCESS / FAILURE. * * * ************************************************************************/inttty_close (struct dinfo *dip){ if (dip->di_closing || dip->di_fd == NoFd) { return (SUCCESS); /* Closing or not open. */ } if (tty_saved == TRUE) { (void) restore_tty (dip->di_fd); } return (close_file (dip));}/************************************************************************ * * * tty_reopen() - Reopen Terminal Devices. * * * * Inputs: dip = The device information pointer. * * oflags = The device/file open flags. * * * * Return Value: * * Returns 0 / -1 = SUCESS / FAILURE. * * * ************************************************************************//*ARGSUSED*/inttty_reopen (struct dinfo *dip, int oflags){ int status = SUCCESS; /* * For terminal devices, we don't close the device since this * resets characteristics which must then be reset. */ if (edelay_count) { /* Optional end delay. */ mySleep (edelay_count); }#ifdef notdef if ((status = reopen_file (dip, oflags)) == SUCCESS) { (void) setup_tty (&dip->di_fd, FALSE); }#else end_of_file = FALSE;#endif /* notdef */ return (status);}/************************************************************************ * * * tty_flush_data() - Wait for tty output queue to empty (drain). * * * * Inputs: dip = The device information pointer. * * * * Return Value: * * Returns 0 / -1 = SUCESS / FAILURE. * * * ************************************************************************/inttty_flush_data (struct dinfo *dip){ return (drain_tty (dip->di_fd));}/************************************************************************ * * * drain_tty() - Wait for tty output data to drain. * * * * Description: * * This function was added to drain the terminal ports' output * * buffer. This is needed to properly synchronize with the process * * reading the data. If the writer exits before the reader reads the * * data with software carrier enabled, the output data gets flushed * * (discarded) by terminal driver. * * * * Inputs: fd = The terminal file descriptor to drain. * * * * Return Value: * * Returns SUCCESS / FAILURE. * * * ************************************************************************/intdrain_tty (int fd){ int status;#if !defined(_QNX_SOURCE) && !defined(__MSDOS__) && !defined(__WIN32__) && !defined(HP_UX) /* * If debug is enabled, display the characters not flushed * in the output queue yet. */ if (debug_flag) { int outq_size; if (ioctl (fd, TIOCOUTQ, &outq_size) < 0) { report_error ("TIOCOUTQ", TRUE); } else { Printf ("Characters remaining in output queue = %d\n", outq_size); } }#endif /* !defined(_QNX_SOURCE) */ /* * Wait for the output queue to drain. */ if (debug_flag) { Printf ("Waiting for output queue to drain...\n"); }#if defined(ultrix) if ((status = ioctl (fd, TCSBRK, -1)) < 0) { if (debug_flag) report_error ("TCSBRK", TRUE);#else /* !defined(ultrix) */ if ((status = tcdrain (fd)) < 0) { report_error ("tcdrain()", TRUE);#endif /* defined(ultrix) */ /* * Since some drivers don't support this ioctl, we must * get and set the terminal characteristics to flush the * output queue (isn't this fun?). */ status = setup_tty (fd, FALSE); } if (debug_flag && (status == SUCCESS) ) { Printf ("Output queue finished draining...\n"); } return (status);}/************************************************************************ * * * flush_tty() - Flush the tty input buffer queue. * * * * Description: * * This function flushs the tty input buffer queue before starting * * the test. Ordinarily this isn't necessary, since the driver flushes * * unread characters after closing, but the timer associated with this * * action (on output) and the setting of CLOCAL, may result in unwanted * * characters waiting to be read. In any case, to avoid race conditions * * we'll flush input here to avoid unwarrented data compare failures. * * * * Logic Changed: * * We only flush the input queue if flushing has been disabled, * * since both the read & write queues are flushed in save_tty(). * * * * Inputs: fd = The terminal file descriptor to flush. * * * * Return Value: * * void * * * ************************************************************************/intflush_tty (int fd){ int status; if (!flush_flag && debug_flag) { /* Flush/display input queue. */ ssize_t count; unsigned char buff; if ((status = setup_tty (fd, TRUE)) < 0) { return (status); } /* * Read & display any characters in the typeahead buffer. */ while ( (count = read (fd, &buff, (size_t) 1)) > (ssize_t) 0) { Printf ("Flushing: %c (%d.) (%#x)\n", buff, buff, buff); } } else if (!flush_flag) { /* * This could be dangerous if the writer starts first. */ if (tcflush (fd, TCIFLUSH) < 0) { /* Flush input queue. */ report_error ("tcflush(TCIFLUSH)", TRUE); } } status = setup_tty (fd, FALSE); return (status);}/************************************************************************ * * * save_tty() - Save The Current Terminal Characteristics. * * * * Inputs: fd = The terminal file descriptor. * * * * Return Value: * * Returns SUCCESS / FAILURE. * * * ************************************************************************/intsave_tty (int fd){ int status = SUCCESS; if (debug_flag) { Printf ("Saving current terminal characteristics, fd = %d...\n", fd); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -