📄 comport.c
字号:
/* comm state */ //logINFO(LOGSRC,"comPortOpen: SetCommState ..."); DCB portDcb; memset(&portDcb, 0, sizeof(DCB)); portDcb.DCBlength = sizeof(DCB); GetCommState(com->portId, &portDcb); portDcb.BaudRate = com->speed; portDcb.fBinary = TRUE; portDcb.fParity = (_dtaParity != NOPARITY)? TRUE : FALSE; portDcb.fOutxCtsFlow = hwFlow? TRUE : FALSE; portDcb.fOutxDsrFlow = hwFlow? TRUE : FALSE; portDcb.fDtrControl = dtrControl; portDcb.fDsrSensitivity = FALSE; portDcb.fTXContinueOnXoff = TRUE; portDcb.fOutX = FALSE; // software flow control not supported portDcb.fInX = FALSE; // software flow control not supported portDcb.fErrorChar = FALSE; portDcb.fNull = FALSE; // discard nulls on read portDcb.fRtsControl = rtsControl; portDcb.fAbortOnError = FALSE; portDcb.XonLim = 0; // software flow control not supported portDcb.XoffLim = 0; // software flow control not supported portDcb.ByteSize = _dtaBits; // 7/8 data bits portDcb.Parity = _dtaParity; // NOPARITY(0), ODDPARITY(1), EVENPARITY(2) portDcb.StopBits = _dtaStop; // 1/2 stop bit portDcb.XonChar = 0; // software flow control not supported portDcb.XoffChar = 0; // software flow control not supported portDcb.ErrorChar = 0; // not used? portDcb.EofChar = 0; // not used? portDcb.EvtChar = 0; // not used? SetCommState(com->portId, &portDcb); /* timeouts */ //logINFO(LOGSRC,"comPortOpen: SetCommTimeouts ..."); if (!comPortSetTimeouts(com, 300L, 400L, 500L)) { logERROR(LOGSRC,"Unable to set ComPort timeouts ..."); comPortClose(com); com->error = COMERR_INIT; return (ComPort_t*)0; } /* success? */ com->open = utTrue; return com;}#else// NOTE: port number indexes start at '0'ComPort_t *comPortOpen(ComPort_t *com, const char *portName, long bps, const char *dataFmt, utBool hwFlow){ /* null structure? */ if (!com) { // internal error logWARNING(LOGSRC,"ComPort structure is 'null'"); return (ComPort_t*)0; } /* clear structure */ comPortInitStruct(com); /* port */ com->port = _comPortPortForName(portName); if (com->port < 0L) { // internal error logWARNING(LOGSRC,"Unrecognized port name: %s", portName); com->error = COMERR_INIT; strCopy(com->name, sizeof(com->name), portName, -1); return (ComPort_t*)0; } _comPortNameForPort(com->name, com->port); _comPortDeviceForPort(com->dev, com->port); logDEBUG(LOGSRC,"ComPort name=%s, port=0x%04lX, dev=%s", com->name, com->port, com->dev); /* special ports */#if defined(COMPORT_SUPPORT_CONSOLE) if (PORT_IsCONSOLE(com->port)) { com->read_fd = fileno(stdin); com->write_fd = fileno(stdout); com->open = utTrue; comPortResetSTDIN(); // disable echo & buffering comPortResetSTDOUT(); // disable buffering return com; }#endif#if defined(COMPORT_SUPPORT_PIPE) if (PORT_IsSPIPE(com->port) || PORT_IsCPIPE(com->port)) { char pipeFile0[64], pipeFile1[64]; if (PORT_IsSPIPE(com->port)) { int pipePort = PORT_Index0(com->port); sprintf(pipeFile0, "%s%d", COM_PIPE_CLIENT_FILE, pipePort); sprintf(pipeFile1, "%s%d", COM_PIPE_SERVER_FILE, pipePort); } else { int pipePort = PORT_Index0(com->port); sprintf(pipeFile1, "%s%d", COM_PIPE_CLIENT_FILE, pipePort); sprintf(pipeFile0, "%s%d", COM_PIPE_SERVER_FILE, pipePort); } /*int err0 =*/ mkfifo(pipeFile0, 0777); /*int err1 =*/ mkfifo(pipeFile1, 0777); // Note: Opening a named pipe may block indefinitely until the far end of the // pipe is also openned! Use with caution! (O_NONBLOCK) if (PORT_IsSPIPE(com->port)) { logDEBUG(LOGSRC,"Openning ComPort server pipe: W(%s) R(%s)", pipeFile1, pipeFile0); com->write_fd = open(pipeFile1, O_WRONLY, 0); com->read_fd = open(pipeFile0, O_RDONLY, 0); } else { logDEBUG(LOGSRC,"Openning ComPort client pipe: W(%s) R(%s)", pipeFile1, pipeFile0); com->read_fd = open(pipeFile0, O_RDONLY, 0); com->write_fd = open(pipeFile1, O_WRONLY, 0); } if ((com->read_fd >= 0) && (com->write_fd >= 0)) { logDEBUG(LOGSRC,"ComPort pipe openned: W(%s) R(%s)", pipeFile1, pipeFile0); com->open = utTrue; return com; } else { logWARNING(LOGSRC,"Unable to open pipe: W(%s) R(%s)", pipeFile1, pipeFile0); if (com->read_fd >= 0) { close(com->read_fd ); com->read_fd = -1; } if (com->write_fd >= 0) { close(com->write_fd); com->write_fd = -1; } com->error = COMERR_INIT; return (ComPort_t*)0; } }#endif#if defined(COMPORT_SUPPORT_SOCKET) if (PORT_IsCSOCK(com->port) || PORT_IsNMEAD(com->port)) { const char *sockHost = CSOCK_SOCKET_HOST; int sockPort = PORT_IsNMEAD(com->port)? NMEAD_SOCKET_PORT : (PORT_Index0(com->port) + CSOCK_SOCKET_PORT_BASE); logINFO(LOGSRC,"Openning client socket [%s:%d] ...", sockHost, sockPort); com->read_fd = socket(AF_INET, SOCK_STREAM, 0); // SOCK_DGRAM if (com->read_fd <= -1) { // unable to open socket logWARNING(LOGSRC,"Unable to open Comport socket"); com->error = COMERR_INIT; return (ComPort_t*)0; } struct hostent *he = gethostbyname(sockHost); if (he == NULL) { // get the host info // unable to resolve host logWARNING(LOGSRC,"Unable to resolve Comport socket host"); close(com->read_fd); com->read_fd = -1; com->error = COMERR_INIT; return (ComPort_t*)0; } struct sockaddr_in their_addr; // connector's address information their_addr.sin_family = AF_INET; // host byte order their_addr.sin_port = htons(sockPort); // short, network byte order their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(their_addr.sin_zero), 0, sizeof(their_addr.sin_zero)); // (8) zero the rest of the struct if (connect(com->read_fd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) < 0) { // Unable to connect to specified host:port logINFO(LOGSRC,"Unable to open connection to %s:%d", sockHost, sockPort); close(com->read_fd); com->read_fd = -1; com->error = COMERR_INIT; return (ComPort_t*)0; } com->write_fd = com->read_fd; com->open = utTrue; return com; } else if (PORT_IsSSOCK(com->port)) { int yes = 1; struct sockaddr_in my_addr; // my address information int sockPort = PORT_Index0(com->port) + CSOCK_SOCKET_PORT_BASE; logINFO(LOGSRC,"Openning server socket [%d] ...", sockPort); int server_fd = socket(AF_INET, SOCK_STREAM, 0); // SOCK_DGRAM if (server_fd <= -1) { // unable to open socket logWARNING(LOGSRC,"Unable to open Comport server socket"); com->error = COMERR_INIT; return (ComPort_t*)0; } if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { // Unable to set server socket options logWARNING(LOGSRC,"Unable to set Comport server socket options"); close(server_fd); com->error = COMERR_INIT; return (ComPort_t*)0; } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(sockPort); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // auto-fill with my IP memset(&my_addr.sin_zero, 0, 8); // zero the rest of the struct if (bind(server_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { // Unable to bind server to specified port logWARNING(LOGSRC,"Unable to bind Comport server socket port"); close(server_fd); com->error = COMERR_INIT; return (ComPort_t*)0; } if (listen(server_fd, 1) == -1) { // Unable to listen on specified port logWARNING(LOGSRC,"Unable to listen on Comport server socket port"); close(server_fd); com->error = COMERR_INIT; return (ComPort_t*)0; } struct sockaddr_in clientAddr; int alen = sizeof(clientAddr); com->read_fd = accept(server_fd, (struct sockaddr *)&clientAddr, &alen); if (com->read_fd <= -1) { // client accept failed logWARNING(LOGSRC,"Unable to accept on Comport server socket port"); close(server_fd); com->error = COMERR_INIT; return (ComPort_t*)0; } com->write_fd = com->read_fd; com->open = utTrue; //close(server_fd); return com; }#endif /* speed */ com->bps = bps; switch (bps) { case BPS_1200: com->speed = B1200; break; case BPS_2400: com->speed = B2400; break; case BPS_4800: com->speed = B4800; break; case BPS_9600: com->speed = B9600; break; case BPS_19200: com->speed = B19200; break; case BPS_38400: com->speed = B38400; break; case BPS_57600: com->speed = B57600; break;#if defined(B76800) case BPS_76800: com->speed = B76800; break; // undefined on Cygwin#endif case BPS_115200: com->speed = B115200; break;#if defined(B921600) case BPS_921600: com->speed = B921600; break; // BlueTooth 'default' speed#endif default: // this would be an internal error logWARNING(LOGSRC,"Unsupport BPS: %s %ld\n", com->dev, com->bps); com->error = COMERR_SPEED; return (ComPort_t*)0; } /* parse "dataFmt" */ int parity = PARITY_8N1; if (!dataFmt || !*dataFmt || strEqualsIgnoreCase(dataFmt,DTAFMT_8N1)) { // 8 data bits, no parity, 1 stop bit (default) parity = PARITY_8N1; } else if (strEqualsIgnoreCase(dataFmt,DTAFMT_8O1)) { // 8 data bits, odd parity, 1 stop bit (non-standard) // not yet supported logWARNING(LOGSRC,"Format not yet supported: %s", dataFmt); } else if (strEqualsIgnoreCase(dataFmt,DTAFMT_8E1)) { // 8 data bits, odd parity, 1 stop bit (non-standard) // not yet supported logWARNING(LOGSRC,"Format not yet supported: %s", dataFmt); } else if (strEqualsIgnoreCase(dataFmt,DTAFMT_7N2)) { // 7 data bits, no parity, 2 stop bits // not yet supported logWARNING(LOGSRC,"Format not yet supported: %s", dataFmt); } else if (strEqualsIgnoreCase(dataFmt,DTAFMT_7E1)) { // 7 data bits, even parity, 1 stop bits parity = PARITY_7E1; } else if (strEqualsIgnoreCase(dataFmt,DTAFMT_7O1)) { // 7 data bits, even parity, 1 stop bits parity = PARITY_7O1; } else { logWARNING(LOGSRC,"Unrecognized data format: %s", dataFmt); } /* open */ //logDEBUG(LOGSRC,"Openning ComPort port=0x%04lX, dev=%s", com->port, com->dev); com->read_fd = open(com->dev, O_RDWR | O_NOCTTY); if (com->read_fd < 0) { // device is currently unavailable (or doesn't exist) logWARNING(LOGSRC,"Unable to open ComPort: %s [%s]", com->dev, strerror(errno)); com->error = COMERR_INIT; return (ComPort_t*)0; } com->write_fd = com->read_fd; // comport read/write file descriptor is the same logDEBUG(LOGSRC,"Openned ComPort port=0x%04lX, dev=%s", com->port, com->dev); /* set up blocking/non-blocking read */ fcntl(com->read_fd, F_SETFL, 0); // blocking reads //fcntl(com->read_fd, F_SETFL, FNDELAY); // non blocking reads /* ComPort configuration */ struct termios options; tcgetattr(com->read_fd, &options); /* BPS */ cfsetispeed(&options, com->speed); cfsetospeed(&options, com->speed); /* control options 'c_cflag' */ com->hwFlow = hwFlow; options.c_cflag |= CREAD; // enable receiver options.c_cflag |= CLOCAL; // local mode if (hwFlow) { options.c_cflag |= CRTSCTS; // enable hardware flow control } else { options.c_cflag &= ~CRTSCTS; // disable hardware flow control } if (parity == PARITY_7E1) { // PARITY_7E1 options.c_cflag |= PARENB; // enable parity options.c_cflag &= ~PARODD; // even parity options.c_cflag &= ~CSTOPB; // 1 stop bit options.c_cflag &= ~CSIZE; // [char size mask] options.c_cflag |= CS7; // 7 bit } else if (parity == PARITY_7O1) { // PARITY_7O1 options.c_cflag |= PARENB; // enable parity options.c_cflag |= PARODD; // odd parity options.c_cflag &= ~CSTOPB; // 1 stop bit options.c_cflag &= ~CSIZE; // [char size mask] options.c_cflag |= CS7; // 7 bit } else { // PARITY_8N1 options.c_cflag &= ~PARENB; // disable parity options.c_cflag &= ~CSTOPB; // 1 stop bit options.c_cflag &= ~CSIZE; // [char size mask] options.c_cflag |= CS8; // 8 bit } options.c_cflag |= HUPCL; // drop DTR when port is closed //options.c_cflag &= LOBLK; // don't block job ctl output (undefined on Cygwin) /* input options 'c_iflag' */ options.c_iflag &= ~(IGNBRK | BRKINT); // ignore break options.c_iflag &= ~(IXON | IXOFF | IXANY); // no software flow control options.c_iflag &= ~PARMRK; // don't mark parity errors options.c_iflag &= ~IGNCR; // don't ignore CR options.c_iflag &= ~INLCR; // don't map NL to CR options.c_iflag &= ~ICRNL; // don't map CR to NL if (options.c_cflag & PARENB) { options.c_iflag |= INPCK; // enable parity checking options.c_iflag |= ISTRIP; // strip parity bit (7th bit) } else { options.c_iflag &= ~INPCK; // DISable parity checking options.c_iflag &= ~ISTRIP; // don't strip parity bit } /* local options 'c_lflag' */ options.c_lflag &= ~ICANON; // set raw mode options.c_lflag &= ~(ECHO | ECHONL); // no echo options.c_lflag &= ~ISIG; // disable SIG* interrupt signals options.c_lflag &= ~IEXTEN; // disable extended functions /* read timeouts 'c_cc' */ options.c_cc[VMIN] = 0; // no minimum number of characters to read options.c_cc[VTIME] = 0; // (deciseconds) 0=block forever (unless FNDELAY was set) /* output options */ options.c_oflag &= ~OPOST; // raw output /* set ComPort options */ // TCSANOW - changes occur immediately // TCSADRAIN - changes occur after output is transmitted // TCSAFLUSH - changes occur after output is transmitted, input discarded if (tcsetattr(com->write_fd, TCSANOW, &options) != 0) { logWARNING(LOGSRC,"ComPort init failed: %s [%s]", com->dev, strerror(errno)); // continue } // From the 'tcsetattr' man page: // Note that tcsetattr() returns success if any of the requested changes could be // successfully carried out. Therefore, when making multiple changes it may be // necessary to follow this call with a further call to tcgetattr() to check that // all changes have been performed successfully. /* other default options */#if defined(VTIME_SUPPORTED) // VTIME doesn't work on Cygwin comPortAddOptions(com, COMOPT_VTIMEOUT);#endif /* return structure */ com->open = utTrue; return com;}#endif // defined(TARGET_WINCE)#if defined(TARGET_WINCE)// not yet implemented#elseComPort_t *comPortReopen(ComPort_t *com){ if (!com) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -