⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 Gcomm is a serial communications program similar to seyon, but more modern, and easier to use. Works
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	const	char	rcsid[] = "$Id: serial.c,v 1.1.1.1 2001/03/08 00:01:47 efalk Exp $" ;#endif#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <signal.h>#include <string.h>#include <ctype.h>#include <sys/ioctl.h>#include <sys/termios.h>#include <sys/types.h>#include <sys/uio.h>#include <sys/time.h>#include "gcomm.h"#include "params.h"#include "pattern.h"#include "dialog.h"#include "buffers.h"#include "winutils.h"static	struct termios old_settings ;static	int	tryOpen(const char *name, int mode) ;static	void	modemBreak() ;static	int	modemDialFirst(), modemDialNext() ;static	void	modemDialDone() ;static	void	SerialDialog() ;	void	SetHardwareFlow() ;static	int	get_baud() ;static	int	get_baudi() ;	int	hangingUp = 0 ;	/* Open serial port.  Set non-blocking.  Get undefined baud rate,	 * character size, stop bits, etc. parameters from hardware.	 * Call SerialSettings() to set hardware from parameters.	 */intSerialOpen(const char *serialname){	int	i,j ;	struct termios new_settings ;	/* first, open the serial port.  Name may be a single	 * device, or a list seperated by commas	 */	if( (ifd = tryOpen(serialname, O_RDWR)) == -1 ) {	  WindowStatus("Cannot open serial port, %s", strerror(errno)) ;	  return -1 ;	}	ofd = ifd ;	i = fcntl(ifd, F_GETFL, 0) ;	j = fcntl(ifd, F_SETFL, i|O_NDELAY) ;	if( tcgetattr(ifd,&old_settings) < 0 ) {	  perror("SerialOpen: tcgetattr:") ;	  return -1 ;	}	/* set any undefined variables to their true value */	if( baudRate == -1 ) {	  baudRate = get_baudi(cfgetospeed(&old_settings)) ;	}	if( byteSize == -1 ) {	  switch( old_settings.c_cflag & CSIZE ) {	    case CS5: byteSize = 5 ; break ;	    case CS6: byteSize = 6 ; break ;	    case CS7: byteSize = 7 ; break ;	    case CS8: byteSize = 8 ; break ;	  }	}	if( stopBits == -1 )	  stopBits = (old_settings.c_cflag & CSTOPB) ? 2 : 1 ;	if( inputStrip == -1 )	  inputStrip = (old_settings.c_iflag & ISTRIP) != 0 ;	if( parityType == -1 ) {	  switch( old_settings.c_cflag & (PARENB|PARODD) ) {	    case 0:	    case PARODD: parityType = ParityNone ; break ;	    case PARENB: parityType = ParityEven ; break ;	    case PARENB|PARODD: parityType = ParityOdd ; break ;	  }	}	if( flowControl == -1 ) {	  if( old_settings.c_cflag | CRTSCTS )	    flowControl = FlowRtsCts ;	  else if( old_settings.c_iflag & (IXON|IXOFF) )	    flowControl = FlowXonXoff ;	  else	    flowControl = FlowNone ;	}	WindowGetSerial() ;	/* update window display */	/* put serial line into as transparent a mode as possible */	new_settings = old_settings ;	new_settings.c_iflag = 0 ;	new_settings.c_oflag &= ~OPOST ;	new_settings.c_lflag = 0 ;	new_settings.c_cc[VMIN] = 16 ;	new_settings.c_cc[VTIME] = 1 ;	if( tcsetattr(ifd,TCSADRAIN, &new_settings) < 0 ) {	  perror("SerialOpen: tcsetattr") ;	  return -1 ;	}	SerialSettings() ;	return 0 ;}	/* utility: attempt to open a list of devices, seperated by commas */static	inttryOpen(const char *name, int type){	char	devname[1024] ;	char	*ptr, *ptr2 ;	int	fd ;	strncpy(devname, name, sizeof(devname)) ;	for(ptr = devname;  ptr != NULL; ptr = ptr2 )	{	  if( (ptr2 = strchr(ptr, ',')) != NULL )	    *ptr2++ = '\0' ;	  if( (fd = open(ptr, type)) != -1 )	    return fd ;	}	return -1 ;}	/* close serial port, restore settings to original values. */intSerialClose(){	if( tcsetattr(ifd,TCSADRAIN, &old_settings) < 0 )	  perror("SerialClose: tcsetattr") ;	close(ifd) ;	ifd = ofd = -1 ;	connectionActive = False ;	modemFlags = 0 ;	WindowModem() ;	return 0 ;}	/* Set hardware flow control from parameters and modem "CD" flag */voidSetHardwareFlow(){	struct termios settings ;	if( ifd == -1 )	  return ;	if( tcgetattr(ifd,&settings) < 0 ) {	  perror("SetHardwareFlow: tcgetattr") ;	  return ;	}	/* TODO: posix-compatible way to do this? */	if( ioctl(ifd, TIOCMGET, &modemFlags) < 0 ) {	  perror("SetHardwareFlow: TIOCMGET") ;	  modemFlags = 0 ;	}	/* Hardware bug:  Some serial ports will not read if	 * hardware flow control is enabled and there is no carrier	 * detect.  Therefore, we only turn on hardware flow control	 * when carrier detect is on	 */	if( flowControl != -1 ) {	  switch( flowControl ) {	    case FlowNone:	      hardwareFlow = 0 ;	      settings.c_iflag &= ~(IXON|IXOFF) ;	      settings.c_cflag &= ~CRTSCTS ;	      break ;	    case FlowXonXoff:	      hardwareFlow = 0 ;	      settings.c_iflag |= IXON|IXOFF ;	      settings.c_cflag &= ~CRTSCTS ;	      break ;	    case FlowRtsCts:	      settings.c_iflag &= ~(IXON|IXOFF) ;	      hardwareFlow = !hangingUp && (modemFlags & TIOCM_CAR) != 0 ;	      if( hardwareFlow )		settings.c_cflag |= CRTSCTS ;	      else		settings.c_cflag &= ~CRTSCTS ;	      break ;	  }	}	if( tcsetattr(ifd,TCSADRAIN, &settings) < 0 )	  perror("SetHardwareFlow: tcsetattr") ;}	/* utility: set serial port */voidSerialPortControl(int baud, int cs, int parity, int stop, bool istrip){	struct termios settings ;	int	i ;	if( ifd == -1 )	  return ;	if( tcgetattr(ifd,&settings) < 0 ) {	  perror("SerialSettings: tcgetattr") ;	  return ;	}	if( baud != -1 ) {	  i = get_baud(baud) ;	  if( i != 0 ) {	    cfsetospeed(&settings, i) ;	    cfsetispeed(&settings, i) ;	  }	}	if( cs >= 5 && cs <= 8 ) {	  static int csizes[] = {CS5,CS6,CS7,CS8} ;	  settings.c_cflag &= ~CSIZE ;	  settings.c_cflag |= csizes[cs-5] ;	}	if( stop >= 1 && stop <= 2 ) {	  if( stop == 2 )	    settings.c_cflag |= CSTOPB ;	  else	    settings.c_cflag &= ~CSTOPB ;	}	if( istrip != -1 ) {	  if( istrip )	    settings.c_iflag |= ISTRIP ;	  else	    settings.c_iflag &= ~ISTRIP ;	}	if( parity != -1 ) {	  switch( parity ) {	    case ParityNone:	      settings.c_cflag &= ~(PARENB|PARODD) ;	      break ;	    case ParityEven:	      settings.c_cflag &= ~PARODD ;	      settings.c_cflag |= PARENB ;	      break ;	    case ParityOdd:	      settings.c_cflag |= PARENB|PARODD ;	      break ;	    case ParityZero:	    case ParityOne:	      /* fake zero/one parity by setting byte size one higher */	      i = settings.c_cflag & CSIZE ;	      if( i < CS8 ) {		i += CS6 ;		settings.c_cflag &= ~CSIZE ;		settings.c_cflag |= i ;	      }	      break ;	  }	}	if( tcsetattr(ifd,TCSADRAIN, &settings) < 0 )	  perror("SerialSettings: tcsetattr") ;}	/* update serial port settings from parameters */voidSerialSettings(){	SerialPortControl(baudRate, byteSize, parityType, stopBits, inputStrip);	SetHardwareFlow() ;}	/* examine and display serial port modem lines */	/* BUG: the Zilog serial ports used by SUN shut down the receiver	 * if Carrier Detect is zero.  Thus, we need to only enable hardware	 * flow control when CD is nonzero.	 */voidSerialModemLines(){	int	oldflags = modemFlags ;	if( ofd >= 0 )	{	  ioctl(ofd, TIOCMGET, &modemFlags) ;	  if( oldflags != modemFlags )	  {	    /* if hardware flow control requested, see if CD changed */	    if( flowControl == FlowRtsCts  &&		((oldflags ^ modemFlags) & TIOCM_CD) )	      SetHardwareFlow() ;	    WindowModem() ;	  }	}}voidSerialFlush(int which){	if( ofd >= 0 )	{	  ioctl(ofd, TCFLSH, which) ;	}}voidSerialBreak(){	if( ofd >= 0 )	{	  ioctl(ofd, TCSBRK, 0) ;	}}	/* convert integer baud rate to termios # */static	intget_baud(int b){	switch(b) {	  case 50: return B50 ;	  case 75: return B75 ;	  case 110: return B110 ;	  case 134: return B134 ;	  case 150: return B150 ;	  case 200: return B200 ;	  case 300: return B300 ;	  case 600: return B600 ;	  case 1200: return B1200 ;	  case 1800: return B1800 ;	  case 2400: return B2400 ;	  case 4800: return B4800 ;	  case 9600: return B9600 ;	  case 19200: return B19200 ;	  case 38400: return B38400 ;	  default: return 0 ;	}}	/* convert termios baud rate to integer */static	intget_baudi(int b){	switch(b) {	  case B50: return 50 ;	  case B75: return 75 ;	  case B110: return 110 ;	  case B134: return 134 ;	  case B150: return 150 ;	  case B200: return 200 ;	  case B300: return 300 ;	  case B600: return 600 ;	  case B1200: return 1200 ;	  case B1800: return 1800 ;	  case B2400: return 2400 ;	  case B4800: return 4800 ;	  case B9600: return 9600 ;	  case B19200: return 19200 ;	  case B38400: return 38400 ;	  default: return 0 ;	}}	/* CONNECT/DISCONNECT dialog functions */	/* Establish a connection according to modem control strings	 * and phone number	 */static	Pattern	ModemPats[] =	  { {"OK\r\n",NULL,0}, {"CONNECT",NULL,0}, {"NO CARRIER\r\n",NULL,0},	  {"BUSY\r\n",NULL,0}, {"ERROR\r\n",NULL,0}, {"NO DIALTONE\r\n",NULL,0} } ;#define	NModemPats	(sizeof(ModemPats)/sizeof(ModemPats[0]))typedef	enum {dSModemConnect, dSModemInit, dSModemSetup, dSModemDialing,	      dSModemDisConnect, dSModemBreak, dSModemHangup, dSModemReset	     } DialogState ;static	DialogState	dState ;static	char	stdResetStr[] = "ATQ0V1" ;static	voiddialogInit(DialogState state, int time){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -