📄 ttyfun.c
字号:
/** Modify Records:* 2007-01-25 when writing tty fails, it need to check the errno,* if errno equals to EINTR or EAGAIN, continue to write.*/#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <fcntl.h> #include <errno.h>#ifndef _LINUX_#define _LINUX_#endif#ifdef _LINUX_#include <termios.h>#include <unistd.h>#include <sys/termios.h>#include <sys/types.h> #include <sys/stat.h>#include <sys/ioctl.h>#else#include <windows.h>#endif#include "ttyfun.h"/*********************************************** extern variales**********************************************/extern char debugType;extern void WMMP_TRACE(char type, const char *format, ...);//interior functions and variablesint gttyfd; //tty file descriptorint opentty(const char *dev);int initialtty(int fd, int inspeed,int databits,int stopbits,int parity,int crtscts);int readtty(int fd, int len, int timeout, void *pRecv, int *pRetLen);int writetty(int fd, int len, int timeout, const void *pSend);int cleartty(int fd);int closetty(int fd);#ifdef _LINUX_void wmmp_set_up_tty(int tty_fd, int local,int inspeed,int crtscts,int parity,int databits,int stopbits,int mode);#define ok_error(num) ((num)==EIO)struct wmmp_speed { int speed_int, speed_val;} wmmp_speeds[] = {#ifdef B50 { 50, B50 },#endif#ifdef B75 { 75, B75 },#endif#ifdef B110 { 110, B110 },#endif#ifdef B134 { 134, B134 },#endif#ifdef B150 { 150, B150 },#endif#ifdef B200 { 200, B200 },#endif#ifdef B300 { 300, B300 },#endif#ifdef B600 { 600, B600 },#endif#ifdef B1200 { 1200, B1200 },#endif#ifdef B1800 { 1800, B1800 },#endif#ifdef B2000 { 2000, B2000 },#endif#ifdef B2400 { 2400, B2400 },#endif#ifdef B3600 { 3600, B3600 },#endif#ifdef B4800 { 4800, B4800 },#endif#ifdef B7200 { 7200, B7200 },#endif#ifdef B9600 { 9600, B9600 },#endif#ifdef B19200 { 19200, B19200 },#endif#ifdef B38400 { 38400, B38400 },#endif#ifdef B57600 { 57600, B57600 },#endif#ifdef B115200 { 115200, B115200 },#endif#ifdef EXTA { 19200, EXTA },#endif#ifdef EXTB { 38400, EXTB },#endif#ifdef B230400 { 230400, B230400 },#endif#ifdef B460800 { 460800, B460800 },#endif { 0, 0 }};static int translate_speed (int bps){ struct wmmp_speed *speedp; if (bps != 0) { for (speedp = wmmp_speeds; speedp->speed_int; speedp++) { if (bps == speedp->speed_int) return speedp->speed_val; } //DAEMON_WMMP_TRACE("speed %d not supported", bps); } return 0;}void wmmp_setdtr (int tty_fd, int on){ int modembits = TIOCM_DTR; //DAEMON_WMMP_TRACE("setdtr,tty_fd:%d,value:%d\n",tty_fd,on); ioctl(tty_fd, (on ? TIOCMBIS : TIOCMBIC), &modembits);}//dev = "/dev/ttyS1"int opentty(const char* dev){ gttyfd = open(dev, O_RDWR|O_NOCTTY|O_NONBLOCK); if(gttyfd < 0) { WMMP_TRACE(debugType, "Error: Open Serial fail!!!\n"); } return gttyfd;}int initialtty(int fd, int inspeed, int databits, int stopbits, int parity, int crtscts){ wmmp_set_up_tty(fd, 0, inspeed, crtscts, parity, databits, stopbits, 0); return 0;}int cleartty(int fd){ tcflush(fd, TCIOFLUSH); return 0;}int closetty(int fd){ int ret = 0; ret = close(fd); if(ret < 0) { WMMP_TRACE(debugType, "Failed to close tty resource\n"); goto closetty_fail; } else { WMMP_TRACE(debugType, "Succ to close tty resource\n"); } return 0;closetty_fail: return -1;}int readtty(int fd, int len, int timeout, void * pRecv, int * pRetLen){ int ret = 0; int iTotalLen = 0; int iLeftLen = 0; int utime= timeout;// * 1000; struct timeval time_start, time_cur; char *pBuf = NULL;//(uchar*)pRecv; iTotalLen = 0; iLeftLen = len; utime = timeout;// * 1000;//ms pBuf = (char*)pRecv; gettimeofday(&time_start, NULL); gettimeofday(&time_cur, NULL); while((time_cur.tv_sec - time_start.tv_sec) < utime) { ret = read(fd, pBuf + iTotalLen, iLeftLen); if(ret >= 0) { iLeftLen -= ret; iTotalLen += ret; } else if(errno == EINTR || errno == EAGAIN) { gettimeofday(&time_cur, NULL); continue; } else { return -1; } if(iLeftLen == 0) { break; } gettimeofday(&time_cur, NULL); } *pRetLen = iTotalLen; WMMP_TRACE(debugType, "\r\nReadTty: %s\r\n", pRecv); return 0;}int writetty(int fd, int len, int timeout, const void *pSend){ int ret = 0; int iLeftLen = 0; int iSentLen = 0; int utime = 0; struct timeval time_start, time_cur; char *pBuf = NULL; iLeftLen = len; iSentLen = 0; utime = timeout;// * 1000; pBuf = (char*)pSend; gettimeofday(&time_start, NULL); gettimeofday(&time_cur, NULL); WMMP_TRACE(debugType, "\r\nWriteTty: %s\r\n", pBuf); while((time_cur.tv_sec - time_start.tv_sec) < utime) { ret = write(fd, pBuf + iSentLen, iLeftLen); if(ret >= 0) { iLeftLen -= ret; iSentLen += ret; } else// if() { if(errno == EINTR || errno == EAGAIN) {//add in 2007-01-25 by ljs WMMP_TRACE(debugType, "Error: INTR or EAGAIN\r\n"); gettimeofday(&time_cur, NULL); continue; } WMMP_TRACE(debugType, "Error: write tty\r\n"); return -1; } if(iLeftLen == 0) { break; } gettimeofday(&time_cur, NULL); } if(iLeftLen > 0) { WMMP_TRACE(debugType, "Error: send not all data\r\n"); return -2; } return 0;}int wait_for_OK(int fd, const char *szMatch, uint uiTime){ char szTemp[1000]; int iRet; int iRetCount = 0; int iLeftCount = 0; ulong utime = uiTime ;// * 1000000; struct timeval time_start, time_cur; memset(szTemp,0x00,sizeof(szTemp)); gettimeofday(&time_start, NULL); gettimeofday(&time_cur, NULL); iLeftCount = sizeof(szTemp); while((time_cur.tv_sec - time_start.tv_sec) < utime) { iRet = read(fd, szTemp+iRetCount, iLeftCount); if(iRet>=0) { iRetCount += iRet; iLeftCount -= iRet; if( (strstr(szTemp,szMatch))!=NULL ) { WMMP_TRACE(debugType, "\r\nreceived string match: %s", szTemp); iRetCount=0; return 0; } if( (strstr(szTemp,"ERROR"))!=NULL ) { WMMP_TRACE(debugType, "\r\nError: received ERROR after sending SMS"); WMMP_TRACE(debugType, "\r\nszTemp: %s", szTemp); return -1; } } else { switch(errno) { case EINTR: case EAGAIN: break; case EBADF: { WMMP_TRACE(debugType, "Read Err: Illegal ttyfd\r\n"); break; } default: { WMMP_TRACE(debugType, "Read Err:Unknown\r\n"); break; } } if(errno == EINTR || errno == EAGAIN) { gettimeofday(&time_cur, NULL); continue; } return -1; } gettimeofday(&time_cur, NULL); } if((time_cur.tv_sec - time_start.tv_sec) >= utime) { WMMP_TRACE(debugType, "Error: wait for OK timeout!\r\n"); WMMP_TRACE(debugType, "szTemp: %s\r\n", szTemp); return -2; } return 0;}void wmmp_set_up_tty(int tty_fd, int local,int inspeed,int crtscts,int parity,int databits,int stopbits,int mode){ int speed; struct termios tios; wmmp_setdtr(tty_fd, 1); if (tcgetattr(tty_fd, &tios) < 0) { if (!ok_error(errno)) WMMP_TRACE(debugType, "\r\ntcgetattr: %m(%d)", errno); return; } //Ignore modem control lines,enable receiver,ignore break tios.c_cflag |= (CLOCAL | CREAD | IGNBRK); switch (parity) { case NO_PARITY: tios.c_cflag &= ~PARENB; /* Clear parity enable */ //tios.c_iflag &= ~INPCK; /* Enable parity checking */ tios.c_iflag &=~(INPCK |ISTRIP); tios.c_iflag |= IGNPAR; break; case ODD_PARITY: tios.c_cflag |= (PARODD | PARENB); tios.c_iflag |= INPCK; /* Disnable parity checking */ break; case EVEN_PARITY: tios.c_cflag |= PARENB; /* Enable parity */ tios.c_cflag &= ~PARODD; tios.c_iflag |= INPCK; /* Disnable parity checking */ break; default: //DAEMON_WMMP_TRACE("Not supported parity,set no parity\n"); tios.c_cflag &= ~PARENB; /* Clear parity enable */ tios.c_iflag &= ~INPCK; /* Enable parity checking */ break; } tios.c_cflag &= ~CSIZE; switch (databits) /**/ { case 7: tios.c_cflag |= CS7; break; case 8: tios.c_cflag |= CS8; break; default: //DAEMON_WMMP_TRACE("Not supported databits,set 8\n"); tios.c_cflag |= CS8; break; } switch (stopbits) { case 1: tios.c_cflag &= ~CSTOPB; break; case 2: tios.c_cflag |= CSTOPB; break; default: //DAEMON_WMMP_TRACE("Not supported stopbits,set 1\n"); tios.c_cflag &= ~CSTOPB; break; } if(mode==0) {//RAW MODE //tios.c_oflag &= ~OPOST; //tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); tios.c_iflag &=~(INLCR | IGNCR | ICRNL); //NL to CR,ignore CR,CR to NL tios.c_lflag=0; tios.c_oflag=0; } switch (crtscts) { case FLOWCTR_HARDWARE: tios.c_cflag |= CRTSCTS; break; case FLOWCTR_XONXOFF: tios.c_iflag |= IXON | IXOFF; tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ break; case FLOWCTR_NONE: tios.c_iflag&=~(IXON|IXOFF|IXANY); tios.c_cflag &= ~CRTSCTS; break; default: break; } tios.c_cc[VMIN] = 1; tios.c_cc[VTIME] = 0; speed = translate_speed(inspeed); if (speed) { cfsetospeed (&tios, speed); cfsetispeed (&tios, speed); }/* * We can't proceed if the serial port speed is B0, * since that implies that the serial port is disabled. */ else { speed = cfgetospeed(&tios); /*if (speed == B0) DAEMON_WMMP_TRACE("Baud rate for ttyS1 is 0; need explicit baud rate");*/ } if (tcsetattr(tty_fd, TCSAFLUSH, &tios) < 0) if (!ok_error(errno)) ;//DAEMON_WMMP_TRACE("error: tcsetattr"); //baud_rate = baud_rate_of(speed); //restore_term = 1;}#else#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <fcntl.h> #include <errno.h>#include <windows.h>#include "ttyfun.h"#include "typedef.h"HANDLE ghCom = INVALID_HANDLE_VALUE;int gttyfd; //tty file descriptorint opentty(const char *dev){ int err = 0; ghCom = CreateFile(dev, /*device name*/ GENERIC_WRITE | GENERIC_READ, /*share mode*/ 0, /**/ NULL, /*no security attr.*/ OPEN_EXISTING, /*comm must be open using OPEN_EXISTING*/ 0, /*not overlapped I/O*/ NULL); /*hTemplate must be NULL for comm devices*/ if(ghCom == INVALID_HANDLE_VALUE) { err = GetLastError(); goto opentty_fail; } gttyfd = (int)ghCom; return gttyfd;opentty_fail: return -1;}int initialtty(int fd, int inspeed,int databits,int stopbits,int parity,int crtscts){ int err = 0; BOOL bRet = FALSE; DCB dcb; char szDcb[50]; COMMTIMEOUTS m_CommTimeouts; //Fill in the DCB: baud, 8 data bits, no parity, and 1 stop bit memset(szDcb, 0, sizeof(szDcb)); sprintf(szDcb, "baud=%d parity=N data=8 stop=1", inspeed); bRet = GetCommState(ghCom, &dcb); if (bRet == FALSE) { err = GetLastError(); goto initialtty_fail; } dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fDtrControl = DTR_CONTROL_ENABLE; bRet = BuildCommDCB(szDcb, &dcb); if (bRet == FALSE) { err = GetLastError(); goto initialtty_fail; } // set the timeout values m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 0; m_CommTimeouts.ReadTotalTimeoutConstant = 500; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000; SetCommTimeouts(ghCom, &m_CommTimeouts); bRet = SetCommState(ghCom, &dcb); if (!bRet) { err = GetLastError(); goto initialtty_fail; } return 0;initialtty_fail: return -1;}//may be problemint readtty(int fd, int len, int timeout, void *pRecv, int *pRetLen){ DWORD dwRet = 0; int iRead = 0; int iRetCount = 0; int iLeftCount = 0; long utime = timeout * 1000; long time_start, time_cur; iLeftCount = len; time_start = GetTickCount(); time_cur = GetTickCount(); while ((time_cur - time_start) < utime) { dwRet = ReadFile(ghCom, (char*)pRecv + iRetCount, iLeftCount, &iRead, NULL); if(dwRet && iRead > 0) {//get some data iRetCount += iRead; iLeftCount -= iRead; } else if (dwRet == 0) { if(errno == EINTR || errno == EAGAIN) { time_cur = GetTickCount(); continue; } goto readtty_fail; } time_cur = GetTickCount(); } *pRetLen = iRetCount; return 0;readtty_fail: return -1;}int writetty(int fd, int len, int timeout, const void *pSend){ DWORD dwRet = 0; DWORD dwWrtn = 0; dwRet = WriteFile(ghCom, pSend, len, &dwWrtn, NULL); if (dwRet == 0 || dwWrtn < (DWORD)len) { goto WriteFile_fail; } return 0;WriteFile_fail: return -1;}//DORD GetTickCount(VOID);//the return value is the number of milliseconds that have elapsed since the system was startedint wait_for_OK(int fd, const char *szMatch, uint uiTime){ char szTemp[1000]; int iRet; int iRetCount = 0; int iLeftCount = 0; int iRead = 0; ulong utime = uiTime*1000; ulong time_start, time_cur; memset(szTemp,0x00,sizeof(szTemp)); iLeftCount = sizeof(szTemp); time_start = GetTickCount(); time_cur = GetTickCount(); while((time_cur - time_start) < utime) { iRet = ReadFile(ghCom, szTemp+iRetCount, iLeftCount, &iRead, NULL); if ( iRet && iRead > 0) { iRetCount += iRead; iLeftCount -= iRead; if( (strstr(szTemp, szMatch))!=NULL ) { iRetCount=0; return 0; } if( (strstr(szTemp,"ERROR"))!=NULL ) { return -1; } } else if(iRet == 0) { if(errno == EINTR || errno == EAGAIN) { time_cur = GetTickCount(); continue; } return -1; } time_cur = GetTickCount(); } if((time_cur - time_start) >= utime) { return -2; } if (strstr(szTemp, szMatch) == NULL) { return -3; } return 0;}int cleartty(int fd){ PurgeComm(ghCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); return 0;}int closetty(int fd){ BOOL bRet = FALSE ; bRet = CloseHandle(ghCom); if(!bRet) { goto closetty_fail; } ghCom = INVALID_HANDLE_VALUE; return 0;closetty_fail: return -1;}int gettotalcomm(char* comm[]){ ulong ulProtNum = 0; char portName[30], commName[7]; DWORD dwLong, dwSize; ulong i=0, ulTemp = 0; HKEY m_hPortKey; if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Hardware\\DeviceMap\\SerialComm", 0, KEY_READ, &m_hPortKey ) == ERROR_SUCCESS) { // 获取注册表子项数 RegQueryInfoKey(m_hPortKey, NULL, NULL, NULL, NULL, NULL, NULL, &ulProtNum, NULL, NULL, 0, 0); while(ulTemp < ulProtNum) { dwLong = dwSize = sizeof(portName); // 枚举串口 if(RegEnumValue(m_hPortKey, i, portName, &dwLong, NULL, NULL, (PUCHAR)commName, &dwSize ) == ERROR_SUCCESS)//ERROR_NO_MORE_ITEMS) { memcpy(comm[ulTemp], commName, strlen(commName)); ulTemp ++; } i++; } } return ulProtNum;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -