int ACE_TTY_IO::control (Control_Mode cmd, Serial_Params *arg) const { #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO) #if defined (ACE_HAS_TERMIOS) struct termios devpar; speed_t newbaudrate = 0; if (tcgetattr (get_handle () , &devpar) == -1) #elif defined (TCGETS) struct termios devpar; unsigned int newbaudrate = 0; if (this->ACE_IO_SAP::control (TCGETS, static_cast<void*>(&devpar)) == -1) #elif defined (TCGETA) struct termio devpar; unsigned int newbaudrate = 0; if (this->ACE_IO_SAP::control (TCGETA, static_cast<void*>(&devpar)) == -1) #else errno = ENOSYS; #endif /* ACE_HAS_TERMIOS */ return -1; switch (cmd) { case SETPARAMS: switch (arg->baudrate) { #if defined (B0) case 0: newbaudrate = B0; break; #endif /* B0 */ #if defined (B50) case 50: newbaudrate = B50; break; #endif /* B50 */ #if defined (B75) case 75: newbaudrate = B75; break; #endif /* B75 */ #if defined (B110) case 110: newbaudrate = B110; break; #endif /* B110 */ #if defined (B134) case 134: newbaudrate = B134; break; #endif /* B134 */ #if defined (B150) case 150: newbaudrate = B150; break; #endif /* B150 */ #if defined (B200) case 200: newbaudrate = B200; break; #endif /* B200 */ #if defined (B300) case 300: newbaudrate = B300; break; #endif /* B300 */ #if defined (B600) case 600: newbaudrate = B600; break; #endif /* B600 */ #if defined (B1200) case 1200: newbaudrate = B1200; break; #endif /* B1200 */ #if defined (B1800) case 1800: newbaudrate = B1800; break; #endif /* B1800 */ #if defined (B2400) case 2400: newbaudrate = B2400; break; #endif /* B2400 */ #if defined (B4800) case 4800: newbaudrate = B4800; break; #endif /* B4800 */ #if defined (B9600) case 9600: newbaudrate = B9600; break; #endif /* B9600 */ #if defined (B19200) case 19200: newbaudrate = B19200; break; #endif /* B19200 */ #if defined (B38400) case 38400: newbaudrate = B38400; break; #endif /* B38400 */ #if defined (B56000) case 56000: newbaudrate = B56000; break; #endif /* B56000 */ #if defined (B57600) case 57600: newbaudrate = B57600; break; #endif /* B57600 */ #if defined (B76800) case 76800: newbaudrate = B76800; break; #endif /* B76800 */ #if defined (B115200) case 115200: newbaudrate = B115200; break; #endif /* B115200 */ #if defined (B128000) case 128000: newbaudrate = B128000; break; #endif /* B128000 */ #if defined (B153600) case 153600: newbaudrate = B153600; break; #endif /* B153600 */ #if defined (B230400) case 230400: newbaudrate = B230400; break; #endif /* B230400 */ #if defined (B307200) case 307200: newbaudrate = B307200; break; #endif /* B307200 */ #if defined (B256000) case 256000: newbaudrate = B256000; break; #endif /* B256000 */ #if defined (B460800) case 460800: newbaudrate = B460800; break; #endif /* B460800 */ #if defined (B500000) case 500000: newbaudrate = B500000; break; #endif /* B500000 */ #if defined (B576000) case 576000: newbaudrate = B576000; break; #endif /* B576000 */ #if defined (B921600) case 921600: newbaudrate = B921600; break; #endif /* B921600 */ #if defined (B1000000) case 1000000: newbaudrate = B1000000; break; #endif /* B1000000 */ #if defined (B1152000) case 1152000: newbaudrate = B1152000; break; #endif /* B1152000 */ #if defined (B1500000) case 1500000: newbaudrate = B1500000; break; #endif /* B1500000 */ #if defined (B2000000) case 2000000: newbaudrate = B2000000; break; #endif /* B2000000 */ #if defined (B2500000) case 2500000: newbaudrate = B2500000; break; #endif /* B2500000 */ #if defined (B3000000) case 3000000: newbaudrate = B3000000; break; #endif /* B3000000 */ #if defined (B3500000) case 3500000: newbaudrate = B3500000; break; #endif /* B3500000 */ #if defined (B4000000) case 4000000: newbaudrate = B4000000; break; #endif /* B4000000 */ default: return -1; } #if defined (ACE_HAS_TERMIOS) // Can you really have different input and output baud rates?! if (cfsetospeed (&devpar, newbaudrate) == -1) return -1; if (cfsetispeed (&devpar, newbaudrate) == -1) return -1; #else devpar.c_cflag &= ~CBAUD; # if defined (CBAUDEX) devpar.c_cflag &= ~CBAUDEX; # endif /* CBAUDEX */ devpar.c_cflag |= newbaudrate; #endif /* ACE_HAS_TERMIOS */ devpar.c_cflag &= ~CSIZE; switch (arg->databits) { case 5: devpar.c_cflag |= CS5; break; case 6: devpar.c_cflag |= CS6; break; case 7: devpar.c_cflag |= CS7; break; case 8: devpar.c_cflag |= CS8; break; default: return -1; } switch (arg->stopbits) { case 1: devpar.c_cflag &= ~CSTOPB; break; case 2: devpar.c_cflag |= CSTOPB; break; default: return -1; } if (arg->paritymode) { if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_ODD) == 0) { devpar.c_cflag |= PARENB; devpar.c_cflag |= PARODD; } else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_EVEN) == 0) { devpar.c_cflag |= PARENB; devpar.c_cflag &= ~PARODD; } else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_NONE) == 0) devpar.c_cflag &= ~PARENB; else return -1; } else { devpar.c_cflag &= ~PARENB; } #if defined (CNEW_RTSCTS) if ((arg->ctsenb) || (arg->rtsenb)) // Enable RTS/CTS protocol devpar.c_cflag |= CNEW_RTSCTS; else devpar.c_cflag &= ~CNEW_RTSCTS; #elif defined (CRTSCTS) if ((arg->ctsenb) || (arg->rtsenb)) // Enable RTS/CTS protocol devpar.c_cflag |= CRTSCTS; else devpar.c_cflag &= ~CRTSCTS; #endif /* NEW_RTSCTS || CRTSCTS */ #if defined (CREAD) // Enable/disable receiver if (arg->rcvenb) devpar.c_cflag |= CREAD; else devpar.c_cflag &= ~CREAD; #endif /* CREAD */ #if defined (HUPCL) // Cause DTR to drop after port close. devpar.c_cflag |= HUPCL; #endif /* HUPCL */ #if defined (CLOCAL) // If device is not a modem set to local device. if (arg->modem) devpar.c_cflag &= ~CLOCAL; else devpar.c_cflag |= CLOCAL; #endif /* CLOCAL */ devpar.c_iflag = IGNPAR | INPCK; if (arg->databits < 8) devpar.c_iflag |= ISTRIP; #if defined (IGNBRK) // If device is not a modem set to ignore break points if(arg->modem) devpar.c_iflag &= ~IGNBRK; else devpar.c_iflag |= IGNBRK; #endif /* IGNBRK */ #if defined (IXOFF) // Enable/disable software flow control on input if (arg->xinenb) devpar.c_iflag |= IXOFF; else devpar.c_iflag &= ~IXOFF; #endif /* IXOFF */ #if defined (IXON) // Enable/disable software flow control on output if (arg->xoutenb) devpar.c_iflag |= IXON; else devpar.c_iflag &= ~IXON; #endif /* IXON */ #if defined (ICANON) // Enable noncanonical input processing mode devpar.c_lflag &= ~ICANON; #endif /* ICANON */ #if defined (ECHO) // Disable echoing of input characters devpar.c_lflag &= ~ECHO; #endif /* ECHO */ #if defined (ECHOE) // Disable echoing erase chareacter as BS-SP-BS devpar.c_lflag &= ~ECHOE; #endif /* ECHOE */ #if defined (ISIG) // Disable SIGINTR, SIGSUSP, SIGDSUSP and SIGQUIT signals devpar.c_lflag &= ~ISIG; #endif /* ISIG */ #if defined (OPOST) // Disable post-processing of output data devpar.c_oflag &= ~OPOST; #endif /* OPOST */ if (arg->readtimeoutmsec < 0) { // Settings for infinite timeout. devpar.c_cc[VTIME] = 0; // In case of infinite timeout [VMIN] must be at least 1. if (arg->readmincharacters > UCHAR_MAX) devpar.c_cc[VMIN] = UCHAR_MAX; else if (arg->readmincharacters < 1) devpar.c_cc[VMIN] = 1; else devpar.c_cc[VMIN] = static_cast<unsigned char>(arg->readmincharacters); } else { devpar.c_cc[VTIME] = static_cast<unsigned char>(arg->readtimeoutmsec / 100); if (arg->readmincharacters > UCHAR_MAX) devpar.c_cc[VMIN] = UCHAR_MAX; else if (arg->readmincharacters < 1) devpar.c_cc[VMIN] = 0; else devpar.c_cc[VMIN] = static_cast<unsigned char>(arg->readmincharacters); } #if defined (TIOCMGET) int status; this->ACE_IO_SAP::control (TIOCMGET, &status); if (arg->dtrdisable) status &= ~TIOCM_DTR; else status |= TIOCM_DTR; this->ACE_IO_SAP::control (TIOCMSET, &status); #endif /* definded (TIOCMGET) */ #if defined (ACE_HAS_TERMIOS) return tcsetattr (get_handle (), TCSANOW, &devpar); #elif defined (TCSETS) return this->ACE_IO_SAP::control (TCSETS, static_cast<void*>(&devpar)); #elif defined (TCSETA) return this->ACE_IO_SAP::control (TCSETA, static_cast<void*>(&devpar)); #else errno = ENOSYS; return -1; #endif /* ACE_HAS_TERMIOS */ case GETPARAMS: return -1; // Not yet implemented. default: return -1; // Wrong cmd. } #elif defined (ACE_WIN32) switch (cmd) { case SETPARAMS: DCB dcb; dcb.DCBlength = sizeof dcb; if (!::GetCommState (this->get_handle (), &dcb)) { ACE_OS::set_errno_to_last_error (); return -1; } dcb.BaudRate = arg->baudrate; switch (arg->databits) { case 4: case 5: case 6: case 7: case 8: dcb.ByteSize = arg->databits; break; default: return -1; } switch (arg->stopbits) { case 1: dcb.StopBits = ONESTOPBIT; break; case 2: dcb.StopBits = TWOSTOPBITS; break; default: return -1; } if (arg->paritymode) { dcb.fParity = TRUE; if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_ODD) == 0) dcb.Parity = ODDPARITY; else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_EVEN) == 0) dcb.Parity = EVENPARITY; else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_NONE) == 0) dcb.Parity = NOPARITY; else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_MARK) == 0) dcb.Parity = MARKPARITY; else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_SPACE) == 0) dcb.Parity = SPACEPARITY; else return -1; } else { dcb.fParity = FALSE; dcb.Parity = NOPARITY; } // Enable/disable RTS protocol. switch (arg->rtsenb) { case 1: dcb.fRtsControl = RTS_CONTROL_ENABLE; break; case 2: dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; break; case 3: dcb.fRtsControl = RTS_CONTROL_TOGGLE; break; default: dcb.fRtsControl = RTS_CONTROL_DISABLE; } // Enable/disable CTS protocol. if (arg->ctsenb) dcb.fOutxCtsFlow = TRUE; else dcb.fOutxCtsFlow = FALSE; // Enable/disable DSR protocol. if (arg->dsrenb) dcb.fOutxDsrFlow = TRUE; else dcb.fOutxDsrFlow = FALSE; // Disable/enable DTR protocol if (arg->dtrdisable) dcb.fDtrControl = DTR_CONTROL_DISABLE; else dcb.fDtrControl = DTR_CONTROL_ENABLE; // Enable/disable software flow control on input if (arg->xinenb) dcb.fInX = TRUE; else dcb.fInX = FALSE; // Enable/disable software flow control on output if (arg->xoutenb) dcb.fOutX = TRUE; else dcb.fOutX = FALSE; // Always set limits unless set to negative to use default. if (arg->xonlim >= 0) dcb.XonLim = static_cast<WORD>(arg->xonlim); if (arg->xofflim >= 0) dcb.XoffLim = static_cast<WORD>(arg->xofflim); dcb.fAbortOnError = FALSE; dcb.fErrorChar = FALSE; dcb.fNull = FALSE; dcb.fBinary = TRUE; if (!::SetCommState (this->get_handle (), &dcb)) { ACE_OS::set_errno_to_last_error (); return -1; } COMMTIMEOUTS timeouts; if (!::GetCommTimeouts (this->get_handle(), &timeouts)) { ACE_OS::set_errno_to_last_error (); return -1; } if (arg->readtimeoutmsec < 0) { // Settings for infinite timeout. timeouts.ReadIntervalTimeout = 0; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 0; } else if (arg->readtimeoutmsec == 0) { // Return immediately if no data in the input buffer. timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 0; } else { // Wait for specified timeout for char to arrive before returning. timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; timeouts.ReadTotalTimeoutConstant = arg->readtimeoutmsec; } if (!::SetCommTimeouts (this->get_handle (), &timeouts)) { ACE_OS::set_errno_to_last_error (); return -1; } return 0; case GETPARAMS: ACE_NOTSUP_RETURN (-1); // Not yet implemented. default: return -1; // Wrong cmd. } // arg switch #else ACE_UNUSED_ARG (cmd); ACE_UNUSED_ARG (arg); ACE_NOTSUP_RETURN (-1); #endif /* ACE_HAS_TERMIOS || ACE_HAS_TERMIO */ }
int /*PORT_NAME*/_setup() { char * device = "/*PATH_TO_DEVICE*/"; uint32_t baudrate = /*BAUDRATE*/; /*TRACE_LEVEL_1*/printf("[/*PORT_NAME*/] Opening Serial device %s at %ibps...\n", device, baudrate); int result; struct termios port_settings; result = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if (result < 0) { /*TRACE_LEVEL_1*/printf("[/*PORT_NAME*/] Error opening Serial port\n"); /*TRACE_LEVEL_1*/perror("Error opening Serial port"); } else if (tcgetattr(result, &port_settings) < 0) {// try to get current options /*TRACE_LEVEL_1*/printf("[/*PORT_NAME*/] Error opening Serial port: could not get serial port attributes\n"); /*TRACE_LEVEL_1*/perror("Error opening Serial port: could not get serial port attributes"); } else { //printf("Configuring port %s...\n", device); switch(baudrate) { case 115200: cfsetispeed(&port_settings, B115200); // set baud rates to 115200 ---------- Test with 57600 cfsetospeed(&port_settings, B115200); break; case 57600: cfsetispeed(&port_settings, B57600); // set baud rates to 115200 ---------- Test with 57600 cfsetospeed(&port_settings, B57600); break; case 38400: cfsetispeed(&port_settings, B38400); // set baud rates to 38400 ---------- Test with 57600 cfsetospeed(&port_settings, B38400); break; case 19200: cfsetispeed(&port_settings, B19200); // set baud rates to 19200 ---------- Test with 57600 cfsetospeed(&port_settings, B19200); break; case 9600: cfsetispeed(&port_settings, B9600); // set baud rates to 115200 ---------- Test with 57600 cfsetospeed(&port_settings, B9600); break; default: cfsetispeed(&port_settings, B115200); // set baud rates to 115200 ---------- Test with 57600 cfsetospeed(&port_settings, B115200); break; } // 8N1 port_settings.c_cflag &= ~PARENB; port_settings.c_cflag &= ~CSTOPB; port_settings.c_cflag &= ~CSIZE; port_settings.c_cflag |= CS8; // no flow control port_settings.c_cflag &= ~CRTSCTS; port_settings.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines port_settings.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl port_settings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw port_settings.c_oflag &= ~OPOST; // make raw // see: http://unixwiz.net/techtips/termios-vmin-vtime.html port_settings.c_cc[VMIN] = 0; port_settings.c_cc[VTIME] = 20; if (tcsetattr(result, TCSANOW, &port_settings) < 0 ) { /*TRACE_LEVEL_1*/printf("[/*PORT_NAME*/] Error opening Serial port: could not set serial port attributes\n"); /*TRACE_LEVEL_1*/perror("Error opening Serial port: could not set serial port attributes"); } sleep(1); // wait a bit } /*PORT_NAME*/_device_id = result; /*TRACE_LEVEL_2*/printf("[/*PORT_NAME*/] Serial Port %s open\n", device); }
int main(int argc, char **argv) { signal(SIGINT, do_cleanup); for(;;) { int options_index = 0; int c = getopt_long(argc, argv, ":", long_options, &options_index); if(c == -1) break; if(c == 1 || c == 2) { if(optarg == NULL) { print_usage(argv[0]); } if(strncmp("true", optarg, 5) == 0) { if(c == 1) bus_pirate_flag = 0; if(c == 2) termiobaud = 1; } } } if (optind + 1 != argc) { print_usage(argv[0]); } device_file = malloc(strlen(argv[optind])+1); memcpy(device_file, argv[optind], strlen(argv[optind])+1); //Initialization complete! devicefd = open(device_file, O_RDWR | O_NOCTTY); if(devicefd == -1) { fprintf(stderr, "E: Cannot open device %s\n", device_file); exit(1); } printf("Device file: %s\n", device_file); if(termiobaud) { struct termios options; speed_t speed = B9600; if(bus_pirate_flag) { speed = B115200; } tcgetattr(devicefd, &options); //8N1 options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; cfsetispeed(&options, speed); cfsetospeed(&options, speed); tcsetattr(devicefd, TCSAFLUSH, &options); } if(bus_pirate_flag) { bp_enter_uart_binary(devicefd); bp_uart_set_power(devicefd, 1); fprintf(stderr, "Entered BP binary mode.\n"); } struct gt511c1r fpr; gt511c1r_init(&fpr, devicefd, do_usrt); gt511c1r_open(&fpr); int userinput = 0; int id = 0; for(;;) { printf("Input number\n" "0 - Exit program\n" "1 - Clear fingerprint memory\n" "2 - Enroll finger\n" "3 - Identify finger\n" "select>"); scanf("%d", &userinput); switch(userinput) { case 0: do_cleanup(); case 1: gt511c1r_delete_all_fingerprint(&fpr); break; case 2: printf("Input slot number: "); scanf("%d", &userinput); if(userinput < 0 || userinput > 19) { printf("Wrong number!\n"); break; } gt511c1r_enroll_fingerprint(&fpr, userinput); break; case 3: printf("Identifying!\n"); id = gt511c1r_identify_fingerprint(&fpr); printf("Identified as fingerprint #%d\n", id); break; default: printf("Not in range!\n"); } } //TODO: Display interactive console. sleep(1); do_cleanup(); return 0; }
////////////////////////////////////////////////////////////////////////////////////////// // Open a communication channel to the given serial port name. XsensResultValue Cmt1s::open( const char* portName, const uint32_t baudRate, uint32_t readBufSize, uint32_t writeBufSize) { MRPT_UNUSED_PARAM(readBufSize); MRPT_UNUSED_PARAM(writeBufSize); m_endTime = 0; CMT1LOG("L1: Open port %s at %d baud\n", portName, baudRate); if (m_isOpen) { CMT1LOG("L1: Port already open\n"); return (m_lastResult = XRV_ALREADYOPEN); } m_baudrate = baudRate; #ifdef _WIN32 char winPortName[32]; // Open port sprintf(winPortName, "\\\\.\\%s", portName); m_handle = CreateFileA( winPortName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); if (m_handle == INVALID_HANDLE_VALUE) { CMT1LOG("L1: Port cannot be opened\n"); return (m_lastResult = XRV_INPUTCANNOTBEOPENED); } // Once here, port is open m_isOpen = true; // Get the current state & then change it GetCommState(m_handle, &m_commState); // Get current state m_commState.BaudRate = baudRate; // Setup the baud rate m_commState.Parity = NOPARITY; // Setup the Parity m_commState.ByteSize = 8; // Setup the data bits m_commState.StopBits = TWOSTOPBITS; // Setup the stop bits m_commState.fDsrSensitivity = FALSE; // Setup the flow control m_commState.fOutxCtsFlow = FALSE; // NoFlowControl: m_commState.fOutxDsrFlow = FALSE; m_commState.fOutX = FALSE; m_commState.fInX = FALSE; if (!SetCommState(m_handle, (LPDCB)&m_commState)) { // Set new state // Bluetooth ports cannot always be opened with 2 stopbits // Now try to open port with 1 stopbit. m_commState.StopBits = ONESTOPBIT; if (!SetCommState(m_handle, (LPDCB)&m_commState)) { CloseHandle(m_handle); m_handle = INVALID_HANDLE_VALUE; m_isOpen = false; return (m_lastResult = XRV_INPUTCANNOTBEOPENED); } } m_port = atoi(&portName[3]); sprintf(m_portname, "%s", portName); setTimeout(m_timeout); // Other initialization functions EscapeCommFunction(m_handle, SETRTS); // Enable RTS (for Xbus Master use) // Set DTR (Calibration sensors need DTR to startup, won't hurt otherwise EscapeCommFunction(m_handle, SETDTR); SetupComm(m_handle, readBufSize, writeBufSize); // Set queue size // Remove any 'old' data in buffer // PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR); PurgeComm( m_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); #else // !_WIN32 // Open port m_handle = ::open(portName, O_RDWR | O_NOCTTY); // O_RDWR: Read+Write // O_NOCTTY: Raw input, no "controlling terminal" // O_NDELAY: Don't care about DCD signal if (m_handle < 0) { // Port not open return m_lastResult = XRV_INPUTCANNOTBEOPENED; } // Once here, port is open m_isOpen = true; /* Start configuring of port for non-canonical transfer mode */ // Get current options for the port tcgetattr(m_handle, &m_commState); // Set baudrate. cfsetispeed(&m_commState, baudRate); cfsetospeed(&m_commState, baudRate); // Enable the receiver and set local mode m_commState.c_cflag |= (CLOCAL | CREAD); // Set character size to data bits and set no parity Mask the characte size // bits m_commState.c_cflag &= ~(CSIZE | PARENB); m_commState.c_cflag |= CS8; // Select 8 data bits m_commState.c_cflag |= CSTOPB; // send 2 stop bits // Disable hardware flow control m_commState.c_cflag &= ~CRTSCTS; m_commState.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); // Disable software flow control m_commState.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); // Set Raw output m_commState.c_oflag &= ~OPOST; // Timeout 0.001 sec for first byte, read minimum of 0 bytes m_commState.c_cc[VMIN] = 0; m_commState.c_cc[VTIME] = (m_timeout + 99) / 100; // 1 // Set the new options for the port tcsetattr(m_handle, TCSANOW, &m_commState); m_port = 0; sprintf(m_portname, "%s", portName); tcflush(m_handle, TCIOFLUSH); // setting RTS and DTR; RTS for Xbus Master, DTR for calibration sensors int cmbits; if (ioctl(m_handle, TIOCMGET, &cmbits) < 0) { return (m_lastResult = XRV_ERROR); } cmbits |= TIOCM_RTS | TIOCM_DTR; if (ioctl(m_handle, TIOCMSET, &cmbits) < 0) { return (m_lastResult = XRV_ERROR); } #endif // !_WIN32 CMT1LOG("L1: Port opened\n"); return (m_lastResult = XRV_OK); }
/** Applies settings to a serial connection (sets baud rate, parity, etc). @param fd The file descriptor corresponding to an open serial connection. @param speed The baud rate to be applied to the connection. @param parity 0=no parity; 1=odd parity; 2=even parity @param vmin 0 = nonblocking; if >=1, block until we have received at least vmin bytes @param vtime If blocking, tenths of a second we should block until we give up. This code is partially based on: https://stackoverflow.com/questions/6947413 */ static void serial_settings(int fd, int speed, int parity, int vmin, int vtime) { /* get current serial port settings */ struct termios toptions; memset(&toptions, 0, sizeof(struct termios)); if(tcgetattr(fd, &toptions) == -1) msg(ERROR, "tcgetattr error: %s\n", strerror(errno)); int baud = 0; switch(speed) { case 100: baud = B110; break; case 300: baud = B300; break; case 600: baud = B600; break; case 1200: baud = B1200; break; case 2400: baud = B2400; break; case 4800: baud = B4800; break; case 9600: baud = B9600; break; //case 14400: baud = B14400; break; // not on Linux case 19200: baud = B19200; break; //case 28800: baud = B28800; break; // not on Linux case 38400: baud = B38400; break; //case 56000: baud = B56000; break; // not on Linux case 57600: baud = B57600; break; case 115200: baud = B115200; break; //case 128000: baud = B128000; break; // not on Linux //case 153600: baud = B153600; break; // not on Linux //case 256000: baud = B256000; break; // not on Linux //case 460800: baud = B460800; break; // not on OSX //case 921600: baud = B921600; break; // not on OSX default: msg(FATAL, "Invalid baud rate specified: %d\n", speed); exit(EXIT_FAILURE); } /* You can verify that the settings are correct by doing: stty -F /dev/ttyUSB0 sane Running this program stty -F /dev/ttyUSB0 stty -F /dev/ttyUSB0 cs8 115200 ignbrk -brkint -icrnl -imaxbel -ixon -icanon -isig -echo -echoe -echok -echoctl -echoke noflsh -iexten -opost -onlcr -crtscts The output of the last two commands should match. The last command is what is apparently what Arduino expects based on a post at http://playground.arduino.cc/Interfacing/LinuxTTY */ /* Set baud rate both directions */ if(cfsetispeed(&toptions, baud) == -1 || cfsetospeed(&toptions, baud) == -1) { msg(ERROR, "Unable to set baud rate to %d\n", speed); } // Input flags // toptions.c_iflag |= IGNBRK; // set bit to ignore break condition (seems to cause issues with bno055 sensor toptions.c_iflag &= ~BRKINT; toptions.c_iflag &= ~ICRNL; toptions.c_iflag &= ~IMAXBEL; toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl // Line processing toptions.c_lflag &= ~ICANON; toptions.c_lflag &= ~ISIG; toptions.c_lflag &= ~ECHO; toptions.c_lflag &= ~ECHOE; toptions.c_lflag &= ~ECHOK; toptions.c_lflag &= ~ECHOCTL; toptions.c_lflag &= ~ECHOKE; toptions.c_lflag |= NOFLSH; toptions.c_lflag &= ~IEXTEN; // Output flags toptions.c_oflag &= ~OPOST; toptions.c_oflag &= ~ONLCR; // Character processing toptions.c_cflag = (toptions.c_cflag & ~CSIZE) | CS8; // 8 bit toptions.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, enable reading toptions.c_cflag &= ~(PARENB | PARODD); // shut off parity if(parity == 1) toptions.c_cflag |= PARENB|PARODD; // enable odd parity else if(parity == 2) toptions.c_cflag |= PARENB; // enable even parity toptions.c_cflag &= ~CSTOPB; // unset two stop bits, use one stop bit toptions.c_cflag &= ~CRTSCTS; // disable hardware flow control toptions.c_cc[VMIN] = vmin; toptions.c_cc[VTIME] = vtime; // If blocking, max time to block in tenths of a second (5 = .5 seconds). cfmakeraw(&toptions); // Apply our new settings, discard data in buffer if(tcsetattr(fd, TCSANOW, &toptions) == -1) msg(ERROR, "tcgetattr error: %s\n", strerror(errno)); serial_discard(fd); }
int xf86SetSerial(int fd, XF86OptionPtr options) { struct termios t; int val; const char *s; int baud, r; if (fd < 0) return -1; /* Don't try to set parameters for non-tty devices. */ if (!isatty(fd)) return 0; SYSCALL(tcgetattr(fd, &t)); if ((val = xf86SetIntOption(options, "BaudRate", 0))) { if ((baud = GetBaud(val))) { cfsetispeed(&t, baud); cfsetospeed(&t, baud); } else { xf86Msg(X_ERROR, "Invalid Option BaudRate value: %d\n", val); return -1; } } if ((val = xf86SetIntOption(options, "StopBits", 0))) { switch (val) { case 1: t.c_cflag &= ~(CSTOPB); break; case 2: t.c_cflag |= CSTOPB; break; default: xf86Msg(X_ERROR, "Invalid Option StopBits value: %d\n", val); return -1; break; } } if ((val = xf86SetIntOption(options, "DataBits", 0))) { switch (val) { case 5: t.c_cflag &= ~(CSIZE); t.c_cflag |= CS5; break; case 6: t.c_cflag &= ~(CSIZE); t.c_cflag |= CS6; break; case 7: t.c_cflag &= ~(CSIZE); t.c_cflag |= CS7; break; case 8: t.c_cflag &= ~(CSIZE); t.c_cflag |= CS8; break; default: xf86Msg(X_ERROR, "Invalid Option DataBits value: %d\n", val); return -1; break; } } if ((s = xf86SetStrOption(options, "Parity", NULL))) { if (xf86NameCmp(s, "Odd") == 0) { t.c_cflag |= PARENB | PARODD; } else if (xf86NameCmp(s, "Even") == 0) { t.c_cflag |= PARENB; t.c_cflag &= ~(PARODD); } else if (xf86NameCmp(s, "None") == 0) { t.c_cflag &= ~(PARENB); } else { xf86Msg(X_ERROR, "Invalid Option Parity value: %s\n", s); return -1; } } if ((val = xf86SetIntOption(options, "Vmin", -1)) != -1) { t.c_cc[VMIN] = val; } if ((val = xf86SetIntOption(options, "Vtime", -1)) != -1) { t.c_cc[VTIME] = val; } if ((s = xf86SetStrOption(options, "FlowControl", NULL))) { xf86MarkOptionUsedByName(options, "FlowControl"); if (xf86NameCmp(s, "Xoff") == 0) { t.c_iflag |= IXOFF; } else if (xf86NameCmp(s, "Xon") == 0) { t.c_iflag |= IXON; } else if (xf86NameCmp(s, "XonXoff") == 0) { t.c_iflag |= IXON | IXOFF; } else if (xf86NameCmp(s, "None") == 0) { t.c_iflag &= ~(IXON | IXOFF); } else { xf86Msg(X_ERROR, "Invalid Option FlowControl value: %s\n", s); return -1; } } if ((xf86SetBoolOption(options, "ClearDTR", FALSE))) { #ifdef CLEARDTR_SUPPORT #if defined(TIOCMBIC) val = TIOCM_DTR; SYSCALL(ioctl(fd, TIOCMBIC, &val)); #else SYSCALL(ioctl(fd, TIOCCDTR, NULL)); #endif #else xf86Msg(X_WARNING, "Option ClearDTR not supported on this OS\n"); return -1; #endif xf86MarkOptionUsedByName(options, "ClearDTR"); } if ((xf86SetBoolOption(options, "ClearRTS", FALSE))) { xf86Msg(X_WARNING, "Option ClearRTS not supported on this OS\n"); return -1; xf86MarkOptionUsedByName(options, "ClearRTS"); } SYSCALL(r = tcsetattr(fd, TCSANOW, &t)); return r; }
value setup(value a, value b) { const char* portName = val_string(a); int baud = val_int(b); //--------------------------------------------- #if defined( TARGET_OSX ) || defined( TARGET_LINUX ) //--------------------------------------------- int fd = open(portName, O_RDWR | O_NOCTTY | O_NONBLOCK); if(fd == -1){ return alloc_null(); } struct termios options; struct termios oldoptions; tcgetattr(fd,&oldoptions); options = oldoptions; switch(baud){ case 300: cfsetispeed(&options,B300); cfsetospeed(&options,B300); break; case 1200: cfsetispeed(&options,B1200); cfsetospeed(&options,B1200); break; case 2400: cfsetispeed(&options,B2400); cfsetospeed(&options,B2400); break; case 4800: cfsetispeed(&options,B4800); cfsetospeed(&options,B4800); break; case 9600: cfsetispeed(&options,B9600); cfsetospeed(&options,B9600); break; #ifdef TARGET_OSX case 14400: cfsetispeed(&options,B14400); cfsetospeed(&options,B14400); break; #endif case 19200: cfsetispeed(&options,B19200); cfsetospeed(&options,B19200); break; #ifdef TARGET_OSX case 28800: cfsetispeed(&options,B28800); cfsetospeed(&options,B28800); break; #endif case 38400: cfsetispeed(&options,B38400); cfsetospeed(&options,B38400); break; case 57600: cfsetispeed(&options,B57600); cfsetospeed(&options,B57600); break; case 115200: cfsetispeed(&options,B115200); cfsetospeed(&options,B115200); break; default: cfsetispeed(&options,B9600); cfsetospeed(&options,B9600); break; } options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~(PARENB | PARODD); options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CRTSCTS; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; if (tcsetattr(fd,TCSANOW,&options) != 0) { return alloc_null(); } return alloc_int(fd); //--------------------------------------------- #endif //--------------------------------------------- //--------------------------------------------- #ifdef TARGET_WIN32 //--------------------------------------------- // open the serial port: // "COM4", etc... HANDLE hComm = CreateFile( portName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if(hComm==INVALID_HANDLE_VALUE){ return alloc_null(); } // now try the settings: COMMCONFIG cfg; DWORD cfgSize; char buf[80]; cfgSize=sizeof(cfg); GetCommConfig(hComm,&cfg,&cfgSize); int bps = baud; sprintf(buf,"baud=%d parity=N data=8 stop=1",bps); #if (_MSC_VER) // microsoft visual studio // msvc doesn't like BuildCommDCB, //so we need to use this version: BuildCommDCBA if(!BuildCommDCBA(buf,&cfg.dcb)){ //ofLog(OF_LOG_ERROR,"ofSerial: unable to build comm dcb; (%s)",buf); } #else if(!BuildCommDCB(buf,&cfg.dcb)){ //ofLog(OF_LOG_ERROR,"ofSerial: Can't build comm dcb; %s",buf); } #endif // Set baudrate and bits etc. // Note that BuildCommDCB() clears XON/XOFF and hardware control by default if(!SetCommState(hComm,&cfg.dcb)){ //ofLog(OF_LOG_ERROR,"ofSerial: Can't set comm state"); } //ofLog(OF_LOG_NOTICE,buf,"bps=%d, xio=%d/%d",cfg.dcb.BaudRate,cfg.dcb.fOutX,cfg.dcb.fInX); // Set communication timeouts (NT) COMMTIMEOUTS tOut; COMMTIMEOUTS oldTimeout; GetCommTimeouts(hComm,&oldTimeout); tOut = oldTimeout; // Make timeout so that: // - return immediately with buffered characters tOut.ReadIntervalTimeout=MAXDWORD; tOut.ReadTotalTimeoutMultiplier=0; tOut.ReadTotalTimeoutConstant=0; SetCommTimeouts(hComm,&tOut); return alloc_int((int)hComm); //--------------------------------------------- #endif //--------------------------------------------- }
int SGConnect() { fdSG = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_NDELAY); if(fdSG == -1) { printf("Can't Connect to Speedgoat USB1. Exiting Program...\n"); return -1; } else { struct termios options2; if(tcgetattr(fdSG,&options2)<0) { printf("Can't get SG Serial Attributes. Exiting Program...\n"); return -1; } else { cfsetospeed(&options2,B9600); cfsetispeed(&options2,B9600); options2.c_cflag &= ~CSTOPB; options2.c_cflag &= ~CSIZE; options2.c_cflag |= CS8; options2.c_cflag |= (CREAD|CLOCAL); if(tcsetattr(fdSG,TCSANOW,&options2)<0) { printf("Can't set SG Serial Attributes. Exiting Program...\n"); return -1; } else { fcntl(fdSG,F_SETFL,0); return 0; } } } }
static NTSTATUS set_baud_rate(int fd, const SERIAL_BAUD_RATE* sbr) { struct termios port; if (tcgetattr(fd, &port) == -1) { ERR("tcgetattr error '%s'\n", strerror(errno)); return FILE_GetNtStatus(); } switch (sbr->BaudRate) { case 0: cfsetospeed( &port, B0 ); break; case 50: cfsetospeed( &port, B50 ); break; case 75: cfsetospeed( &port, B75 ); break; case 110: case CBR_110: cfsetospeed( &port, B110 ); break; case 134: cfsetospeed( &port, B134 ); break; case 150: cfsetospeed( &port, B150 ); break; case 200: cfsetospeed( &port, B200 ); break; case 300: case CBR_300: cfsetospeed( &port, B300 ); break; case 600: case CBR_600: cfsetospeed( &port, B600 ); break; case 1200: case CBR_1200: cfsetospeed( &port, B1200 ); break; case 1800: cfsetospeed( &port, B1800 ); break; case 2400: case CBR_2400: cfsetospeed( &port, B2400 ); break; case 4800: case CBR_4800: cfsetospeed( &port, B4800 ); break; case 9600: case CBR_9600: cfsetospeed( &port, B9600 ); break; case 19200: case CBR_19200: cfsetospeed( &port, B19200 ); break; case 38400: case CBR_38400: cfsetospeed( &port, B38400 ); break; #ifdef B57600 case 57600: cfsetospeed( &port, B57600 ); break; #endif #ifdef B115200 case 115200: cfsetospeed( &port, B115200 ); break; #endif #ifdef B230400 case 230400: cfsetospeed( &port, B230400 ); break; #endif #ifdef B460800 case 460800: cfsetospeed( &port, B460800 ); break; #endif default: #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL) { struct serial_struct nuts; int arby; ioctl(fd, TIOCGSERIAL, &nuts); nuts.custom_divisor = nuts.baud_base / sbr->BaudRate; if (!(nuts.custom_divisor)) nuts.custom_divisor = 1; arby = nuts.baud_base / nuts.custom_divisor; nuts.flags &= ~ASYNC_SPD_MASK; nuts.flags |= ASYNC_SPD_CUST; WARN("You (or a program acting at your behest) have specified\n" "a non-standard baud rate %d. Wine will set the rate to %d,\n" "which is as close as we can get by our present understanding of your\n" "hardware. I hope you know what you are doing. Any disruption Wine\n" "has caused to your linux system can be undone with setserial\n" "(see man setserial). If you have incapacitated a Hayes type modem,\n" "reset it and it will probably recover.\n", sbr->BaudRate, arby); ioctl(fd, TIOCSSERIAL, &nuts); cfsetospeed( &port, B38400 ); } break; #else /* Don't have linux/serial.h or lack TIOCSSERIAL */ ERR("baudrate %d\n", sbr->BaudRate); return STATUS_NOT_SUPPORTED; #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */ } cfsetispeed( &port, cfgetospeed(&port) ); if (tcsetattr(fd, TCSANOW, &port) == -1) { ERR("tcsetattr error '%s'\n", strerror(errno)); return FILE_GetNtStatus(); } return STATUS_SUCCESS; }
/******************************************************************** * open_weatherstation, Windows version * * Input: devicename (COM1, COM2 etc) * * Returns: Handle to the weatherstation (type WEATHERSTATION) * ********************************************************************/ WEATHERSTATION open_weatherstation (char *device) { WEATHERSTATION ws; struct termios adtio; unsigned char buffer[BUFFER_SIZE]; long i; print_log(1,"open_weatherstation"); //calibrate nanodelay function microdelay_init(1); // Set up gpi pointer for direct register access setup_io(); // Switch GPIO 7..11 to output mode /************************************************************************\ * You are about to change the GPIO settings of your computer. * * Mess this up and it will stop working! * * It might be a good idea to 'sync' before running this program * * so at least you still have your code changes written to the SD-card! * \************************************************************************/ // Set GPIO pins 7-11 to output for (g=7; g<=11; g++) { INP_GPIO(g); // must use INP_GPIO before we can use OUT_GPIO OUT_GPIO(g); } //Setup serial port if ((ws = open(device, O_RDWR | O_NOCTTY)) < 0) { printf("\nUnable to open serial device %s\n", device); exit(EXIT_FAILURE); } if ( flock(ws, LOCK_EX) < 0 ) { perror("\nSerial device is locked by other program\n"); exit(EXIT_FAILURE); } //We want full control of what is set and simply reset the entire adtio struct memset(&adtio, 0, sizeof(adtio)); // Serial control options adtio.c_cflag &= ~PARENB; // No parity adtio.c_cflag &= ~CSTOPB; // One stop bit adtio.c_cflag &= ~CSIZE; // Character size mask adtio.c_cflag |= CS8; // Character size 8 bits adtio.c_cflag |= CREAD; // Enable Receiver //adtio.c_cflag &= ~CREAD; // Disable Receiver adtio.c_cflag &= ~HUPCL; // No "hangup" adtio.c_cflag &= ~CRTSCTS; // No flowcontrol adtio.c_cflag |= CLOCAL; // Ignore modem control lines // Baudrate, for newer systems cfsetispeed(&adtio, BAUDRATE); cfsetospeed(&adtio, BAUDRATE); // Serial local options: adtio.c_lflag // Raw input = clear ICANON, ECHO, ECHOE, and ISIG // Disable misc other local features = clear FLUSHO, NOFLSH, TOSTOP, PENDIN, and IEXTEN // So we actually clear all flags in adtio.c_lflag adtio.c_lflag = 0; // Serial input options: adtio.c_iflag // Disable parity check = clear INPCK, PARMRK, and ISTRIP // Disable software flow control = clear IXON, IXOFF, and IXANY // Disable any translation of CR and LF = clear INLCR, IGNCR, and ICRNL // Ignore break condition on input = set IGNBRK // Ignore parity errors just in case = set IGNPAR; // So we can clear all flags except IGNBRK and IGNPAR adtio.c_iflag = IGNBRK|IGNPAR; // Serial output options // Raw output should disable all other output options adtio.c_oflag &= ~OPOST; adtio.c_cc[VTIME] = 10; // timer 1s adtio.c_cc[VMIN] = 0; // blocking read until 1 char if (tcsetattr(ws, TCSANOW, &adtio) < 0) { printf("Unable to initialize serial device"); exit(0); } tcflush(ws, TCIOFLUSH); for (i = 0; i < 448; i++) { buffer[i] = 'U'; } write(ws, buffer, 448); set_DTR(ws,0); set_RTS(ws,0); i = 0; do { sleep_short(10); i++; } while (i < INIT_WAIT && !get_DSR(ws)); if (i == INIT_WAIT) { print_log(2,"Connection timeout 1"); printf ("Connection timeout\n"); close_weatherstation(ws); exit(0); } i = 0; do { sleep_short(10); i++; } while (i < INIT_WAIT && get_DSR(ws)); if (i != INIT_WAIT) { set_RTS(ws,1); set_DTR(ws,1); } else { print_log(2,"Connection timeout 2"); printf ("Connection timeout\n"); close_weatherstation(ws); exit(0); } write(ws, buffer, 448); return ws; }
int serialimu_connect() { int i,j=0; // Open file to write to fp=fopen("DataFile","w"); if(fp==NULL) { perror("First Attempt Error: Data File Not Created/Opened"); fp=fopen("DataFile","w"); if(fp==NULL) { perror("Second Attempt Error: Data File Not Created/Opened"); return -1; // Unsuccessful - Can't Open File to write to } } /*Setup USB serial connection*/ else { // Attempt to connect to serial port fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { perror("First Attempt Error: Unable to open port /dev/ttyUSB0 - "); fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { perror("Second Attempt Error: Unable to open /dev/ttyUSB0 - "); return -2; // Unsuccessful - Can't Connected to Serial } } // Successfully connected to serial port else { struct termios options; if (tcgetattr(fd, &options) < 0) { perror("First Attempt Error: Couldn't get term attributes"); if (tcgetattr(fd, &options) < 0) { perror("First Attempt Error: Couldn't get term attributes"); return -3; } } else { redoattribute: // BAUD RATE SET cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); /* 8N2*/ //options.c_cflag &= PARENB; //Parity Enable options.c_cflag &= ~CSTOPB; //Send two stop bits, else one options.c_cflag &= ~CSIZE; //Character size options.c_cflag |= CS8; //8 bits options.c_cflag &= ~CRTSCTS; options.c_cflag |= CREAD | CLOCAL; /* turn on READ & ignore ctrl lines*/ options.c_iflag &= ~(IXON | IXOFF | IXANY); /* turn off s/w flow ctrl*/ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; /* make raw*/ options.c_cflag &= ~HUPCL;//NEW ADDITION, DISSABLE HANGUP ON if(tcsetattr(fd, TCSANOW, &options) < 0 && j==0) { perror("First Attempt Error: Couldn't set term attributes"); goto redoattribute; j++; } else if(tcsetattr(fd, TCSANOW, &options) < 0 && j>0) { perror("Second Attempt Error: Couldn't set term attributes"); return -3; } else { // Fill Buffer with New Line Char for(i=0; i<buf_siz; ++i) buffer[i]='\n'; } } } } return 0; }
/*====================================== *Function: set_com_config *description:Setting up the serial port parameters *Author: zorro *Created Date :6/18/2015 *======================================*/ int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits) { struct termios options; int speed; /*Save and test the existing serial interface parameter Settings, here if the serial number and other errors, There will be a relevant error message*/ if (tcgetattr(fd, &options) != 0){ perror("tcgetattr"); printf("\n\n\nzorro, tcgetattr err: %s\n", strerror(errno)); return -1; } /*set the character size*/ cfmakeraw(&options); /*configured to the original model*/ options.c_cflag &= ~CSIZE; /*set the baud rate*/ switch (baud_rate){ case 2400: { speed = B2400; } break; case 4800: { speed = B4800; } break; case 9600: { speed = B9600; } break; case 19200: { speed = B19200; } break; case 38400: { speed = B38400; } break; default: case 115200: { speed = B115200; } break; } cfsetispeed(&options, speed); cfsetospeed(&options, speed); /* set the stop bit */ switch (data_bits){ case 7: { options.c_cflag |= CS7; } break; default: case 8: { options.c_cflag |= CS8; } break; } /* Set the parity bit */ switch (parity){ default: case 'n': case 'N': { options.c_cflag &= ~PARENB; options.c_iflag &= ~INPCK; } break; case 'o': case 'O': { options.c_cflag |= (PARODD | PARENB); options.c_iflag |= INPCK; } break; case 'e': case 'E': { options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_iflag |= INPCK; } break; case 's': /*as no parity*/ case 'S': { options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; } break; } switch (stop_bits){ default: case 1: { options.c_cflag &= ~CSTOPB; } break; case 2: { options.c_cflag |= CSTOPB; } break; } /*Set the waiting time and minimum received characters*/ options.c_cc[VTIME] = 0; options.c_cc[VMIN] = 1; /*Handle not receive characters, clean the receive or transmit buff*/ tcflush(fd, TCIFLUSH); /*Activate the new configuration*/ if ((tcsetattr(fd, TCSANOW, &options)) !=0){ perror("tcsetattr"); printf("\n\n\nzorro, tcsetattr err: %s\n", strerror(errno)); return -1; } return 0; }
C_RESULT vp_com_serial_open(vp_com_serial_config_t* config, vp_com_connection_t* connection, vp_com_socket_t* socket, Read* read, Write* write) { struct termios tio; speed_t speed; VP_OS_ASSERT(config->blocking == 0 || config->blocking == 1); if(config->blocking == 0) socket->priv = (void *)open(&config->itfName[0], O_RDWR|O_NOCTTY|O_NONBLOCK); else socket->priv = (void *)open(&config->itfName[0], O_RDWR|O_NOCTTY); if(((int)socket->priv) == -1) { PRINT("Unable to \"open\" serial device"); return (VP_COM_ERROR); } /* get current serial port settings */ if(tcgetattr((int)socket->priv, &tio) != 0) { PRINT("Serial device configuration failure (%s)", strerror(errno)); close((int)socket->priv); return (VP_COM_ERROR); } tio_save = tio; if(config->sync) { /* set serial settings */ speed = (speed_t)config->initial_baudrate; cfsetispeed(&tio, speed); cfsetospeed(&tio, speed); cfmakeraw(&tio); if(tcsetattr((int)socket->priv, TCSANOW, &tio) != 0) { PRINT("Serial device configuration failure (%s)", strerror(errno)); close((int)socket->priv); return (VP_COM_ERROR); } if(socket->type == VP_COM_CLIENT) { if(FAILED(vp_com_serial_write_sync(config, socket))) return (VP_COM_ERROR); vp_os_delay(VP_COM_SYNC_DELAY); } else if(socket->type == VP_COM_SERVER) { if(FAILED(vp_com_serial_wait_sync(config, socket))) return (VP_COM_ERROR); vp_os_delay(VP_COM_SYNC_DELAY); } } /* set serial settings */ speed = (speed_t)config->baudrate; cfsetispeed(&tio, speed); cfsetospeed(&tio, speed); cfmakeraw(&tio); if(tcsetattr((int)socket->priv, TCSANOW, &tio) != 0) { PRINT("Serial device configuration failure (%s)", strerror(errno)); close((int)socket->priv); return (VP_COM_ERROR); } if(read) *read = (Read) vp_com_serial_read; if(write) *write = (Write) vp_com_serial_write; return (VP_COM_OK); }
int UART_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity) { int i; // int status; int speed_arr[] = {B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300 }; int name_arr[] = { 115200,38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300 }; struct termios options; if(tcgetattr( fd,&options) != 0){ perror("SetupSerial 1"); return(FALSE); } for(i= 0;i < sizeof(speed_arr) / sizeof(int);i++) { if (speed == name_arr[i]) { cfsetispeed(&options, speed_arr[i]); cfsetospeed(&options, speed_arr[i]); } } options.c_cflag |= CLOCAL; options.c_cflag |= CREAD; switch(flow_ctrl){ case 0 : options.c_cflag &= ~CRTSCTS; break; case 1 : options.c_cflag |= CRTSCTS; break; case 2 : options.c_cflag |= IXON | IXOFF | IXANY; break; } options.c_cflag &= ~CSIZE; switch (databits){ case 5 : options.c_cflag |= CS5; break; case 6 : options.c_cflag |= CS6; break; case 7 : options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size\n"); return (FALSE); } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; options.c_iflag &= ~INPCK; break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); options.c_iflag |= INPCK; break; case 'e': case 'E': options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_iflag |= INPCK; break; case 's': case 'S': options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,"Unsupported parity\n"); return (FALSE); } switch (stopbits){ case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits\n"); return (FALSE); } options.c_oflag &= ~OPOST; options.c_cc[VTIME] = 1; options.c_cc[VMIN] = 1; tcflush(fd,TCIFLUSH); if(tcsetattr(fd,TCSANOW,&options) != 0){ perror("com set error!\n"); return (FALSE); } return (TRUE); }
int ser_setup( ser_handler id, uint32_t baud, int databits, int parity, int stopbits ) { struct termios termdata; struct timespec tsleep; int hnd = ( int )id; tsleep.tv_sec = 0; tsleep.tv_nsec = 200000000; nanosleep( &tsleep, NULL ); tcgetattr( hnd, &termdata ); // Baud rate cfsetispeed( &termdata, ser_baud_to_id( baud ) ); cfsetospeed( &termdata, ser_baud_to_id( baud ) ); // Parity / stop bits if ( stopbits == SER_STOPBITS_2) { termdata.c_cflag |= CSTOPB; } else { termdata.c_cflag &= ~CSTOPB; } if( parity == SER_PARITY_NONE ) // no parity { termdata.c_cflag &= ~PARENB; } else if( parity == SER_PARITY_EVEN ) // even parity { termdata.c_cflag |= PARENB; termdata.c_cflag &= ~PARODD; } else if( parity == SER_PARITY_ODD ) // odd parity { termdata.c_cflag |= PARENB; termdata.c_cflag |= PARODD; } // Data bits termdata.c_cflag |= ( CLOCAL | CREAD ); termdata.c_cflag &= ~CSIZE; termdata.c_cflag |= ser_number_of_bits_to_id( databits ); // Disable HW and SW flow control #if defined( CRTSCTS ) // not available on all platforms, use if available termdata.c_cflag &= ~CRTSCTS; #endif termdata.c_iflag &= ~( IXON | IXOFF | IXANY ); // Raw input termdata.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG ); // Raw output termdata.c_oflag &= ~OPOST; // Check and strip parity bit if needed if( parity == SER_PARITY_NONE ) termdata.c_iflag &= ~( INPCK | ISTRIP ); else termdata.c_iflag |= ( INPCK | ISTRIP ); // Set the attibutes now tcsetattr( hnd, TCSANOW, &termdata ); // Flush everything tcflush( hnd, TCIOFLUSH ); // And set blocking mode by default fcntl( id, F_SETFL, 0 ); return SER_OK; }
/* Function: mdlStart ======================================================= * Abstract: * This function is called once at start of model execution. If you * have states that should be initialized once, this is the place * to do it. */ static void mdlStart(SimStruct *S) { fdPOT = open("/dev/ttyUSB.ARD1", O_RDWR | O_NOCTTY | O_NDELAY); if (fdPOT == -1) { perror("open_port: Unable to open /dev/ttyUSB.ARD1"); fdPOT = open("/dev/ttyUSB.ARD2", O_RDWR | O_NOCTTY | O_NDELAY); if (fdPOT == -1) { perror("open_port: Unable to open /dev/ttyUSB.ARD2 - "); } } /* else * fcntl(fd, F_SETFL, 0);*/ struct termios options; if (tcgetattr(fdPOT, &options) < 0) { perror("init_serialport: Couldn't get term attributes"); exit(1); } /*BAUD RATE SET, MUST MATCH ARDUINOS!!!*/ /*cfsetispeed(&options, B115200); * cfsetospeed(&options, B115200);*/ cfsetispeed(&options, B9600); cfsetospeed(&options, B9600); /* 8N1*/ options.c_cflag &= ~PARENB; //Parity Enable options.c_cflag &= ~CSTOPB; //Send two stop bits, else one options.c_cflag &= ~CSIZE; //Character size options.c_cflag |= CS8; //8 bits options.c_cflag &= ~CRTSCTS; options.c_cflag |= CREAD | CLOCAL; /* turn on READ & ignore ctrl lines*/ options.c_iflag &= ~(IXON | IXOFF | IXANY); /* turn off s/w flow ctrl*/ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; /* make raw*/ options.c_cflag &= ~HUPCL;/* NEW ADDITION, DISSABLE HANGUP ON CLOSE*/ /* see: http://unixwiz.net/techtips/termios-vmin-vtime.html * options.c_cc[VMIN] = 0; * options.c_cc[VTIME] = 20;*/ if( tcsetattr(fdPOT, TCSANOW, &options) < 0) { perror("init_serialport: Couldn't set term attributes"); exit(1); } //Clear buffer int jread = 0; int jwrite = 0; char Msg = 0; char P1msg[20]; jwrite=write(fdPOT, &Msg, 1); usleep(10000); jread=read(fdPOT, &P1msg, 20); //printf("jread = %d \n",jread); while (jread == -1) { jwrite=write(fdPOT, &Msg, 1); usleep(10000); jread=read(fdPOT, &P1msg, 20); //printf("jread = %d \n",jread); } sleep(1);/*Pause for one second to assure connection*/ }
int xf86OpenSerial(XF86OptionPtr options) { struct termios t; int fd, i; char *dev; dev = xf86SetStrOption(options, "Device", NULL); if (!dev) { xf86Msg(X_ERROR, "xf86OpenSerial: No Device specified.\n"); return -1; } fd = xf86CheckIntOption(options, "fd", -1); if (fd == -1) #ifndef X_PRIVSEP SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK)); #else fd = priv_open_device(dev); #endif if (fd == -1) { xf86Msg(X_ERROR, "xf86OpenSerial: Cannot open device %s\n\t%s.\n", dev, strerror(errno)); free(dev); return -1; } if (!isatty(fd)) { /* Allow non-tty devices to be opened. */ free(dev); return fd; } /* set up default port parameters */ SYSCALL(tcgetattr(fd, &t)); t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); t.c_oflag &= ~OPOST; t.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); t.c_cflag &= ~(CSIZE | PARENB); t.c_cflag |= CS8 | CLOCAL; cfsetispeed(&t, B9600); cfsetospeed(&t, B9600); t.c_cc[VMIN] = 1; t.c_cc[VTIME] = 0; SYSCALL(tcsetattr(fd, TCSANOW, &t)); if (xf86SetSerial(fd, options) == -1) { SYSCALL(close(fd)); free(dev); return -1; } SYSCALL(i = fcntl(fd, F_GETFL, 0)); if (i == -1) { SYSCALL(close(fd)); free(dev); return -1; } i &= ~O_NONBLOCK; SYSCALL(i = fcntl(fd, F_SETFL, i)); if (i == -1) { SYSCALL(close(fd)); free(dev); return -1; } free(dev); return fd; }
/******************************************************************* * 名称: UART0_Set * 功能: 设置串口数据位,停止位和效验位 * 入口参数: fd 串口文件描述符 * speed 串口速度 * flow_ctrl 数据流控制 * databits 数据位 取值为 7 或者8 * stopbits 停止位 取值为 1 或者2 * parity 效验类型 取值为N,E,O,,S *出口参数: 正确返回为1,错误返回为0 *******************************************************************/ static int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity) { unsigned int i; int speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300}; int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300}; struct termios options; /*tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数还可以测试配置是否正确,该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1. */ if ( tcgetattr( fd,&options) != 0) { perror("SetupSerial 1"); return(-1); } //设置串口输入波特率和输出波特率 for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr[i]) { cfsetispeed(&options, speed_arr[i]); cfsetospeed(&options, speed_arr[i]); } } //修改控制模式,保证程序不会占用串口 options.c_cflag |= CLOCAL; //修改控制模式,使得能够从串口中读取输入数据 options.c_cflag |= CREAD; //设置数据流控制 switch(flow_ctrl) { case 0 ://不使用流控制 options.c_cflag &= ~CRTSCTS; break; case 1 ://使用硬件流控制 options.c_cflag |= CRTSCTS; break; case 2 ://使用软件流控制 options.c_cflag |= IXON | IXOFF | IXANY; break; } //设置数据位 //屏蔽其他标志位 options.c_cflag &= ~CSIZE; switch (databits) { case 5 : options.c_cflag |= CS5; break; case 6 : options.c_cflag |= CS6; break; case 7 : options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr,"Unsupported data size\n"); return (-1); } //设置校验位 switch (parity) { case 'n': case 'N': //无奇偶校验位。 options.c_cflag &= ~PARENB; options.c_iflag &= ~INPCK; break; case 'o': case 'O'://设置为奇校验 options.c_cflag |= (PARODD | PARENB); options.c_iflag |= INPCK; break; case 'e': case 'E'://设置为偶校验 options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_iflag |= INPCK; break; case 's': case 'S': //设置为空格 options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr,"Unsupported parity\n"); return (-1); } // 设置停止位 switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr,"Unsupported stop bits\n"); return (-1); } //修改输出模式,原始数据输出 options.c_oflag &= ~OPOST; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);//我加的 //options.c_lflag &= ~(ISIG | ICANON); cfmakeraw(&options); //设置等待时间和最小接收字符 options.c_cc[VTIME] = 1; options.c_cc[VMIN] = 4; //如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读 tcflush(fd,TCIFLUSH); //激活配置 (将修改后的termios数据设置到串口中) if (tcsetattr(fd,TCSANOW,&options) != 0) { perror("com set error!\n"); return (-1); } return (0); }
int main(int argc, char ** argv) { int r; int handle; struct termios attr; char * name = argv[0]; char * device = 0; struct stat statbuf; int pid = 0; setProgName(argv[0]); while (argc > 1) { if (strcasecmp(argv[1], "-w") == 0) { writeonly = 1; } else if (strcasecmp(argv[1], "-p") == 0) { passthru = 1; } else if (strcasecmp(argv[1], "-r") == 0) { readonly = 1; } else if (strcasecmp(argv[1], "-v") == 0) { verbose = 1; } else if (strcasecmp(argv[1], "-t") == 0 && argc > 2) { argc--; argv++; timeout = strtol(argv[1], 0, 10); logDebug("timeout set to %ld seconds\n", timeout); } else if (strcasecmp(argv[1], "-d") == 0) { debug = 1; setLogLevel(LOGLEVEL_DEBUG); } else if (!device) { device = argv[1]; } else { device = 0; break; } argc--; argv++; } if (!device) { fprintf(stderr, "Usage: %s [-w] -[-p] [-r] [-v] [-d] [-t <n>] device\n" "\n" "Options:\n" " -w writeonly mode, no data is read from device\n" " -r readonly mode, no data is sent to device\n" " -p passthru mode, data on stdin is sent to stdout but not to device\n" " -v verbose\n" " -d debug\n" " -t <n> timeout, if no message is received after <n> seconds the program quits\n" " <device> can be a serial device, a normal file containing a raw log,\n" " or the address of a TCP server in the format tcp://<host>[:<port>]\n" "\n" " Examples: %s /dev/ttyUSB0\n" " %s tcp://192.168.1.1:10001\n" "\n" COPYRIGHT, name, name, name); exit(1); } retry: if (debug) fprintf(stderr, "Opening %s\n", device); if (strncmp(device, "tcp:", STRSIZE("tcp:")) == 0) { handle = open_socket_stream(device); if (debug) fprintf(stderr, "socket = %d\n", handle); isFile = true; if (handle < 0) { fprintf(stderr, "Cannot open NGT-1-A TCP stream %s\n", device); exit(1); } } else { handle = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK); if (debug) fprintf(stderr, "fd = %d\n", handle); if (handle < 0) { fprintf(stderr, "Cannot open NGT-1-A device %s\n", device); exit(1); } if (fstat(handle, &statbuf) < 0) { fprintf(stderr, "Cannot determine device %s\n", device); exit(1); } isFile = S_ISREG(statbuf.st_mode); } if (isFile) { if (debug) fprintf(stderr, "Device is a normal file, do not set the attributes.\n"); } else { if (debug) fprintf(stderr, "Device is a serial port, set the attributes.\n"); memset(&attr, 0, sizeof(attr)); cfsetispeed(&attr, B115200); cfsetospeed(&attr, B115200); attr.c_cflag |= CS8 | CLOCAL | CREAD; attr.c_iflag |= IGNPAR; attr.c_cc[VMIN] = 1; attr.c_cc[VTIME] = 0; tcflush(handle, TCIFLUSH); tcsetattr(handle, TCSANOW, &attr); if (debug) fprintf(stderr, "Device is a serial port, send the startup sequence.\n"); writeMessage(handle, NGT_MSG_SEND, NGT_STARTUP_SEQ, sizeof(NGT_STARTUP_SEQ)); sleep(2); } for (;;) { unsigned char msg[BUFFER_SIZE]; size_t msgLen; enum ReadyDescriptor r; r = isready(writeonly ? -1 : handle, readonly ? -1 : 0); if ((r & FD1_Ready) > 0) { if (!readNGT1(handle)) { break; } } if ((r & FD2_Ready) > 0) { if (!readIn(msg, sizeof(msg))) { break; } if (!passthru) { parseAndWriteIn(handle, msg); } fprintf(stdout, "%s", msg); fflush(stdout); } else if (writeonly) { break; } } close(handle); return 0; }
int tty_connect(const char *device, int bit_rate, int word_size, int parity, int stop_bits, int *fd) { #ifdef _WIN32 return TTY_PORT_FAILURE; #else int t_fd = -1; char msg[80]; int bps; struct termios tty_setting; if ((t_fd = open(device, O_RDWR | O_NOCTTY)) == -1) { *fd = -1; return TTY_PORT_FAILURE; } /* Control Modes Set bps rate */ switch (bit_rate) { case 0: bps = B0; break; case 50: bps = B50; break; case 75: bps = B75; break; case 110: bps = B110; break; case 134: bps = B134; break; case 150: bps = B150; break; case 200: bps = B200; break; case 300: bps = B300; break; case 600: bps = B600; break; case 1200: bps = B1200; break; case 1800: bps = B1800; break; case 2400: bps = B2400; break; case 4800: bps = B4800; break; case 9600: bps = B9600; break; case 19200: bps = B19200; break; case 38400: bps = B38400; break; case 57600: bps = B57600; break; case 115200: bps = B115200; break; case 230400: bps = B230400; break; default: if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid bit rate.", bit_rate) < 0) perror(NULL); else perror(msg); return TTY_PARAM_ERROR; } if ((cfsetispeed(&tty_setting, bps) < 0) || (cfsetospeed(&tty_setting, bps) < 0)) { perror("tty_connect: failed setting bit rate."); return TTY_PORT_FAILURE; } /* Control Modes set no flow control word size, parity and stop bits. Also don't hangup automatically and ignore modem status. Finally enable receiving characters. */ tty_setting.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | HUPCL | CRTSCTS); tty_setting.c_cflag |= (CLOCAL | CREAD); /* word size */ switch (word_size) { case 5: tty_setting.c_cflag |= CS5; break; case 6: tty_setting.c_cflag |= CS6; break; case 7: tty_setting.c_cflag |= CS7; break; case 8: tty_setting.c_cflag |= CS8; break; default: fprintf(stderr, "Default\n"); if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid data bit count.", word_size) < 0) perror(NULL); else perror(msg); return TTY_PARAM_ERROR; } /* parity */ switch (parity) { case PARITY_NONE: break; case PARITY_EVEN: tty_setting.c_cflag |= PARENB; break; case PARITY_ODD: tty_setting.c_cflag |= PARENB | PARODD; break; default: fprintf(stderr, "Default1\n"); if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid parity selection value.", parity) < 0) perror(NULL); else perror(msg); return TTY_PARAM_ERROR; } /* stop_bits */ switch (stop_bits) { case 1: break; case 2: tty_setting.c_cflag |= CSTOPB; break; default: fprintf(stderr, "Default2\n"); if (snprintf(msg, sizeof(msg), "tty_connect: %d is not a valid stop bit count.", stop_bits) < 0) perror(NULL); else perror(msg); return TTY_PARAM_ERROR; } /* Control Modes complete */ /* Ignore bytes with parity errors and make terminal raw and dumb.*/ tty_setting.c_iflag &= ~(PARMRK | ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON | IXANY); tty_setting.c_iflag |= INPCK | IGNPAR | IGNBRK; /* Raw output.*/ tty_setting.c_oflag &= ~(OPOST | ONLCR); /* Local Modes Don't echo characters. Don't generate signals. Don't process any characters.*/ tty_setting.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN | NOFLSH | TOSTOP); tty_setting.c_lflag |= NOFLSH; /* blocking read until 1 char arrives */ tty_setting.c_cc[VMIN] = 1; tty_setting.c_cc[VTIME] = 0; /* now clear input and output buffers and activate the new terminal settings */ tcflush(t_fd, TCIOFLUSH); if (tcsetattr(t_fd, TCSANOW, &tty_setting)) { perror("tty_connect: failed setting attributes on serial port."); tty_disconnect(t_fd); return TTY_PORT_FAILURE; } *fd = t_fd; /* return success */ return TTY_OK; #endif }
int setup(int fd, OpenBaton *data) { UnixPlatformOptions* platformOptions = static_cast<UnixPlatformOptions*>(data->platformOptions); int baudRate = ToBaudConstant(data->baudRate); int dataBits = ToDataBitsConstant(data->dataBits); if(dataBits == -1) { snprintf(data->errorString, sizeof(data->errorString), "Invalid data bits setting %d", data->dataBits); return -1; } //Snow Leopard doesn't have O_CLOEXEC int cloexec = fcntl(fd, F_SETFD, FD_CLOEXEC); if (cloexec == -1) { snprintf(data->errorString, sizeof(data->errorString), "Cannot open %s", data->path); return -1; } // struct sigaction saio; // saio.sa_handler = sigio_handler; // sigemptyset(&saio.sa_mask); // saio.sa_flags = 0; // sigaction(SIGIO, &saio, NULL); // //all process to receive SIGIO // fcntl(fd, F_SETOWN, getpid()); // int flflags = fcntl(fd, F_GETFL); // fcntl(fd, F_SETFL, flflags | FNONBLOCK); struct termios options; // Set baud and other configuration. tcgetattr(fd, &options); // Removing check for valid BaudRates due to ticket: #140 // #if not ( defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) ) // Specify the baud rate // On linux you can alter the meaning of B38400 to mean a custom baudrate... #if defined(__linux__) && defined(ASYNC_SPD_CUST) if (baudRate == -1) { struct serial_struct serinfo; serinfo.reserved_char[0] = 0; if (ioctl(fd, TIOCGSERIAL, &serinfo) != -1) { serinfo.flags &= ~ASYNC_SPD_MASK; serinfo.flags |= ASYNC_SPD_CUST; serinfo.custom_divisor = (serinfo.baud_base + (data->baudRate / 2)) / data->baudRate; if (serinfo.custom_divisor < 1) serinfo.custom_divisor = 1; ioctl(fd, TIOCSSERIAL, &serinfo); ioctl(fd, TIOCGSERIAL, &serinfo); // if (serinfo.custom_divisor * rate != serinfo.baud_base) { // warnx("actual baudrate is %d / %d = %f", // serinfo.baud_base, serinfo.custom_divisor, // (float)serinfo.baud_base / serinfo.custom_divisor); // } } // Now we use "B38400" to trigger the special baud rate. baudRate = B38400; } #endif if (baudRate != -1) { cfsetispeed(&options, baudRate); cfsetospeed(&options, baudRate); } // Removing check for valid BaudRates due to ticket: #140 // #endif /* IGNPAR : ignore bytes with parity errors */ options.c_iflag = IGNPAR; /* ICRNL : map CR to NL (otherwise a CR input on the other computer will not terminate input) */ // Pulling this for now. It should be an option, however. -Giseburt //options.c_iflag = ICRNL; // otherwise make device raw (no other input processing) // Specify data bits options.c_cflag &= ~CSIZE; options.c_cflag |= dataBits; options.c_cflag &= ~(CRTSCTS); if (data->rtscts) { options.c_cflag |= CRTSCTS; // evaluate specific flow control options } options.c_iflag &= ~(IXON | IXOFF | IXANY); if (data->xon) { options.c_iflag |= IXON; } if (data->xoff) { options.c_iflag |= IXOFF; } if (data->xany) { options.c_iflag |= IXANY; } switch (data->parity) { case SERIALPORT_PARITY_NONE: options.c_cflag &= ~PARENB; // options.c_cflag &= ~CSTOPB; // options.c_cflag &= ~CSIZE; // options.c_cflag |= CS8; break; case SERIALPORT_PARITY_ODD: options.c_cflag |= PARENB; options.c_cflag |= PARODD; // options.c_cflag &= ~CSTOPB; // options.c_cflag &= ~CSIZE; // options.c_cflag |= CS7; break; case SERIALPORT_PARITY_EVEN: options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; // options.c_cflag &= ~CSTOPB; // options.c_cflag &= ~CSIZE; // options.c_cflag |= CS7; break; default: snprintf(data->errorString, sizeof(data->errorString), "Invalid parity setting %d", data->parity); return -1; } switch(data->stopBits) { case SERIALPORT_STOPBITS_ONE: options.c_cflag &= ~CSTOPB; break; case SERIALPORT_STOPBITS_TWO: options.c_cflag |= CSTOPB; break; default: snprintf(data->errorString, sizeof(data->errorString), "Invalid stop bits setting %d", data->stopBits); return -1; } options.c_cflag |= CLOCAL; //ignore status lines options.c_cflag |= CREAD; //enable receiver if(data->hupcl) { options.c_cflag |= HUPCL; //drop DTR (i.e. hangup) on close } // Raw output options.c_oflag = 0; // ICANON makes partial lines not readable. It should be otional. // It works with ICRNL. -Giseburt options.c_lflag = 0; //ICANON; options.c_cc[VMIN]= platformOptions->vmin; options.c_cc[VTIME]= platformOptions->vtime; // removed this unneeded sleep. // sleep(1); tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &options); // On OS X, starting in Tiger, we can set a custom baud rate, as follows: #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) if (baudRate == -1) { speed_t speed = data->baudRate; if (ioctl(fd, IOSSIOSPEED, &speed) == -1) { snprintf(data->errorString, sizeof(data->errorString), "Error %s calling ioctl( ..., IOSSIOSPEED, %ld )", strerror(errno), speed ); return -1; } } #endif return 1; }
int main (int argc, char *argv[]) { int serial_d; speed_t speed; struct termios soptions, soptions_org; char command; unsigned char send_buf[BUFLEN]; unsigned char recv_buf[BUFLEN]; int sent_c, recv_c; char move; //no port specified if (argc == 1) { printf("Parameter: /dev/ttyUSB0 [command]\n"); printf("\"/dev/ttyUSB0\" is a USB serial device to support serial control.\n"); return 1; } serial_d = openserial(argv[1]); if (serial_d == -1) return 1; // ----- Begin of setup serial ports tcgetattr(serial_d, &soptions_org); tcgetattr(serial_d, &soptions); speed = B9600; // Speed options: B19200, B38400, B57600, B115200 cfsetispeed(&soptions, speed); cfsetospeed(&soptions, speed); // Enable the reciver and set local mode... soptions.c_cflag |= ( CLOCAL | CREAD ); // Setting Parity Checking (8N1) soptions.c_cflag &= ~PARENB; soptions.c_cflag &= ~CSTOPB; soptions.c_cflag &= ~CSIZE; soptions.c_cflag |= CS8; // Local setting //soptions.c_lflag = (ICANON | ECHO | ECHOE); //canonical soptions.c_lflag = ~(ICANON | ECHO | ECHOE | ISIG); //noncanonical // Input setting //soptions.c_iflag |= (IXON | IXOFF | IXANY); //software flow control soptions.c_iflag |= (INPCK | ISTRIP); soptions.c_iflag = IGNPAR; // Output setting soptions.c_oflag = 0; soptions.c_oflag &= ~OPOST; // Read options soptions.c_cc[VTIME] = 0; soptions.c_cc[VMIN] = 1; //transfer at least 1 character or block // Apply setting tcsetattr(serial_d, TCSANOW, &soptions); // ----- End of setup serial ports map[mapsize-1][0]=wall; // left down corner =wall map[mapsize-2][0]=wall; map[mapsize-1][1]=wall; map[mapsize-2][1]=visit; state =0; x=1; y=8; int i,j,k; int* package; char p[10]; int start =0; //system("./plotmap.pyc &"); while (1) { printf("Receiving Data\n"); /* printf("Enter command ('q' to exit): "); command = getchar(); clean_buffer(); if (command == 'q') { printf ("Bye!\n"); break; } printf("Sending command '%c'...\n", command); sent_c = write(serial_d, &command, 1); // Send command tcdrain(serial_d); */ usleep(1000000); // Wait for response if(start ==0) { memset(recv_buf, '\0', BUFLEN); recv_c = read(serial_d, recv_buf, BUFLEN); // Get response message tcdrain(serial_d); if(recv_buf[0] == 'g') start =1; else start=0; } else{ for(k=0; k<5;k++){ memset(recv_buf, '\0', BUFLEN); recv_c = read(serial_d, recv_buf, BUFLEN); // Get response message tcdrain(serial_d); printf("%c\n", recv_buf[0]); p[k] = recv_buf[0]; } } package =Decode(p); move = p[1]; state = package[0]; lb = package[1]; fb = package[2]; rb = package[3]; printf("parameter %d %c %d %d %d\n",p[0],p[1],p[2],p[3],p[4]); printf("parameter %d %c %d %d %d\n",state,move,lb,fb,rb); //Draw Record(state); state = walk(state,move); map[y][x]=visit; //printf("%c %d %d %d\n",move,x,y,state); FILE *f = fopen("map.txt","w"); for(i=0;i<mapsize;i++){ for(j=0;j<mapsize;j++){ printf("%d ",map[i][j]); fprintf(f,"%d ",map[i][j]); } printf("\n"); fprintf(f,"\n"); } fclose(f); //system("./plotmap.pyc &"); } // restore setting and close tcsetattr(serial_d, TCSANOW, &soptions_org); close(serial_d); return 0; }
int GPS::setBaudrate(unsigned baud) { #if __PX4_QURT // TODO: currently QURT does not support configuration with termios. dspal_serial_ioctl_data_rate data_rate; switch (baud) { case 9600: data_rate.bit_rate = DSPAL_SIO_BITRATE_9600; break; case 19200: data_rate.bit_rate = DSPAL_SIO_BITRATE_19200; break; case 38400: data_rate.bit_rate = DSPAL_SIO_BITRATE_38400; break; case 57600: data_rate.bit_rate = DSPAL_SIO_BITRATE_57600; break; case 115200: data_rate.bit_rate = DSPAL_SIO_BITRATE_115200; break; default: PX4_ERR("ERR: unknown baudrate: %d", baud); return -EINVAL; } int ret = ::ioctl(_serial_fd, SERIAL_IOCTL_SET_DATA_RATE, (void *)&data_rate); if (ret != 0) { return ret; } #else /* process baud rate */ int speed; switch (baud) { case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; default: PX4_ERR("ERR: unknown baudrate: %d", baud); return -EINVAL; } struct termios uart_config; int termios_state; /* fill the struct for the new configuration */ tcgetattr(_serial_fd, &uart_config); /* properly configure the terminal (see also https://en.wikibooks.org/wiki/Serial_Programming/termios ) */ // // Input flags - Turn off input processing // // convert break to null byte, no CR to NL translation, // no NL to CR translation, don't mark parity errors or breaks // no input parity check, don't strip high bit off, // no XON/XOFF software flow control // uart_config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); // // Output flags - Turn off output processing // // no CR to NL translation, no NL to CR-NL translation, // no NL to CR translation, no column 0 CR suppression, // no Ctrl-D suppression, no fill characters, no case mapping, // no local output processing // // config.c_oflag &= ~(OCRNL | ONLCR | ONLRET | // ONOCR | ONOEOT| OFILL | OLCUC | OPOST); uart_config.c_oflag = 0; // // No line processing // // echo off, echo newline off, canonical mode off, // extended input processing off, signal chars off // uart_config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); /* no parity, one stop bit */ uart_config.c_cflag &= ~(CSTOPB | PARENB); /* set baud rate */ if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) { GPS_ERR("ERR: %d (cfsetispeed)", termios_state); return -1; } if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) { GPS_ERR("ERR: %d (cfsetospeed)", termios_state); return -1; } if ((termios_state = tcsetattr(_serial_fd, TCSANOW, &uart_config)) < 0) { GPS_ERR("ERR: %d (tcsetattr)", termios_state); return -1; } #endif return 0; }
void set_baudrate(struct termios *newtio,char *data) { switch(atoi(data)) { case 110: cfsetispeed(newtio, B110); cfsetospeed(newtio, B110); break; case 134: cfsetispeed(newtio, B134); cfsetospeed(newtio, B134); break; case 150: cfsetispeed(newtio, B150); cfsetospeed(newtio, B150); break; case 300: cfsetispeed(newtio, B300); cfsetospeed(newtio, B300); break; case 600: cfsetispeed(newtio, B600); cfsetospeed(newtio, B600); break; case 1200: cfsetispeed(newtio, B1200); cfsetospeed(newtio, B1200); break; case 2400: cfsetispeed(newtio, B2400); cfsetospeed(newtio, B2400); break; case 4800: cfsetispeed(newtio, B4800); cfsetospeed(newtio, B4800); break; case 9600: cfsetispeed(newtio, B9600); cfsetospeed(newtio, B9600); break; case 19200: cfsetispeed(newtio, B19200); cfsetospeed(newtio, B19200); break; case 38400: cfsetispeed(newtio, B38400); cfsetospeed(newtio, B38400); break; case 57600: cfsetispeed(newtio, B57600); cfsetospeed(newtio, B57600); break; case 115200: cfsetispeed(newtio, B115200); cfsetospeed(newtio, B115200); break; case 230400: cfsetispeed(newtio, B230400); cfsetospeed(newtio, B230400); break; default: printf("Baudrate %s is wrong!!\n",data); break; } }
/* Baud rate hell. Status in 2015 seems to be : - termios2 struct + BOTHER flag + TCSETS2 ioctl; questionable availability - ASYNC_SPD_CUST + B38400 + custom divisor trick is "deprecated", and needs the linux TIOCSSERIAL ioctl (far from ubiquitous) - take a chance with cfsetispeed etc. with an integer argument, if B9600 == 9600 (non standard, shot in the dark except maybe on BSD??) - use nearest standard speed + cfsetispeed - OSX >10.4 : (unconfirmed, TODO) : IOSSIOSPEED ioctl ? - BSD ? (unconfirmed, TODO) : IOSSIOSPEED ioctl ? */ int _tty_setspeed(struct diag_l0_device *dl0d, unsigned int spd) { struct unix_tty_int *uti = (struct unix_tty_int *)dl0d->tty_int; unsigned int spd_real; //validate baud rate precision struct termios st_new; int spd_done=0; //flag success int rv, fd; fd = uti->fd; const unsigned int std_table[]= { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, #ifdef B57600 57600, #endif #ifdef B115200 115200 #endif }; //std_names must match speeds in std_table ! const speed_t std_names[]= { B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800, B9600, B19200, B38400, #ifdef B57600 B57600, #endif #ifdef B115200 B115200 #endif }; st_new = uti->st_cur; #if defined(__linux__) && defined(USE_TERMIOS2) /* Try setting BOTHER flag in .c_cflag, and literal speed in .c_ispeed */ while (!spd_done) { struct termios2 st2; st2 = uti->st2_cur; st2.c_cflag &= ~CBAUD; st2.c_cflag |= BOTHER; st2.c_ispeed = spd; st2.c_ospeed = spd; if ((rv=ioctl(fd, TCSETS2, &st2)) != 0) break; //re-read to get actual speed if ((rv=ioctl(fd, TCGETS2, &uti->st2_cur)) != 0) break; spd_real = uti->st2_cur.c_ospeed; spd_done = 1; //Setting other flags without termios2 would "erase" speed, //unless TCGETS returns a "safe" termios? if ((rv=ioctl(fd, TCGETS, &uti->st_cur)) != 0) break; if (diag_l0_debug & DIAG_DEBUG_IOCTL) { fprintf(stderr, FLFMT "Speed set using TCSETS + BOTHER.\n", FL); } return spd_real; } if (rv != 0) fprintf(stderr, FLFMT "setspeed(BOTHER) ioctl failed: %s.\n", FL, strerror(errno)); #endif // BOTHER flag trick #if defined(__linux__) && (SEL_TTYBAUD==S_ALT2 || SEL_TTYBAUD==S_AUTO) //#pragma message("Warning : using deprecated ASYNC_SPD_CUST method as a fallback.") /* * Linux iX86 method of setting non-standard baud rates. * This method is apparently deprecated, or at the very least not recommended * and definitely not supported by all hardware because of TIOCSSERIAL. * * Works by manually setting the baud rate divisor and special flags. * */ if (uti->tioc_works && !spd_done) { struct serial_struct ss_new; /* Copy current settings to working copy */ ss_new = uti->ss_cur; /* Now, mod the "current" settings */ ss_new.custom_divisor = ss_new.baud_base / spd; spd_real = ss_new.baud_base / ss_new.custom_divisor; /* Turn of other speed flags */ ss_new.flags &= ~ASYNC_SPD_MASK; /* * Turn on custom speed flags and low latency mode */ ss_new.flags |= ASYNC_SPD_CUST | ASYNC_LOW_LATENCY; /* And tell the kernel the new settings */ if (ioctl(fd, TIOCSSERIAL, &ss_new) < 0) { fprintf(stderr, FLFMT "setspeed(cust): ioctl failed: %s\n", FL, strerror(errno)); return 0; } //sucess : update current settings uti->ss_cur = ss_new; /* * Set the baud rate and force speed to 38400 so that the * custom baud rate stuff set above works */ st_new.c_cflag &= ~CBAUD; st_new.c_cflag |= B38400; spd_done = 1; if (diag_l0_debug & DIAG_DEBUG_IOCTL) { fprintf(stderr, FLFMT "Speed set using TIOCSSERIAL + ASYNC_SPD_CUST.\n", FL); } } #endif //deprecated ASYNC_SPD_CUST trick /* "POSIXY" version of setting non-standard baud rates. * This works at least for FreeBSD. * * POSIX states that it is unspecified what will happen with an * unsupported baud rate. On FreeBSD, the baud rate defines match the * baud rate (i.e., B9600 == 9600), and it attempts to set the baud * rate you pass in, only complaining if the result is off by more * than three percent. * * Unfortunately, I tried this on Mac OS X, and Mac OS X asserts that * the baud rate must match one of the selections. A little research * shows that not only does their iokit driver Serial class permit * only the specific baud rates in the termios header, but at least * the sample driver asserts the requested baud rate is 50 or more. * I don't have the source code for the driver for the Keyspan device * I can't tell if it would work if I modified the iokit serial class. * * use either spd_nearest (currently == nearest Bxxx value) as-is, * or use spd (only if B9600 == 9600, etc.) */ while (!spd_done) { errno = 0; int spd_nearest=0; //index of nearest std value int32_t besterror=1000; for (size_t i=0; i< ARRAY_SIZE(std_table); i++) { int32_t test; test = 1000 * ((long int)spd - std_table[i]) / spd; test = (test >= 0)? test : -test; if (test < besterror) { besterror = test; spd_nearest = i; spd_real = std_table[i]; } } #if (B9600 == 9600) && (SEL_TTYBAUD==S_ALT3 || SEL_TTYBAUD==S_AUTO) //try feeding the speed directly if ( !cfsetispeed(&st_new, spd) && !cfsetospeed(&st_new, spd)) { spd_real = spd; spd_done = 1; if (diag_l0_debug & DIAG_DEBUG_IOCTL) { fprintf(stderr, FLFMT "Speed set with cfset*speed(uint).\n", FL); } break; } fprintf(stderr, "cfset*speed with direct speed failed: %s\n", strerror(errno)); #endif if ( !cfsetispeed(&st_new, std_names[spd_nearest]) && !cfsetospeed(&st_new, std_names[spd_nearest])) { //spd_real already ok spd_done = 1; if (diag_l0_debug & DIAG_DEBUG_IOCTL) { fprintf(stderr, FLFMT "Speed set with cfset*speed(B%u).\n", FL, std_table[spd_nearest]); } break; } fprintf(stderr, "cfset*speed with Bxxxx failed: %s\n", strerror(errno)); break; } //while !spd_done for cfset*speed attempts if (!spd_done) { fprintf(stderr, "Error : all attempts at changing speed failed !\n"); return 0; } #ifdef USE_TERMIOS2 //should never get here anyway return 0; #else errno = 0; for (int retries=1; retries <=10; retries++) { /* Apparently this sometimes failed with EINTR, so we retry. */ rv=tcsetattr(fd, TCSAFLUSH, &st_new); if (rv == 0) { break; } else { fprintf(stderr, FLFMT "Couldn't set baud rate....retry %d\n", FL, retries); continue; } } if (rv != 0) { fprintf(stderr, FLFMT "Can't set baud rate to %u: %s.\n", FL, spd, strerror(errno)); return 0; } #endif return spd_real; }
/* * Class: android_serialport_SerialPort * Method: open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */ JNIEXPORT jobject JNICALL Java_com_example_snapsatpayload_SerialPort_open (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags) { int fd; speed_t speed; jobject mFileDescriptor; /* Check arguments */ { speed = getBaudrate(baudrate); if (speed == -1) { /* TODO: throw an exception */ LOGE("Invalid baudrate"); return NULL; } } /* Opening device */ { jboolean iscopy; const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy); LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags); fd = open(path_utf, O_RDWR | flags); LOGD("open() fd = %d", fd); (*env)->ReleaseStringUTFChars(env, path, path_utf); if (fd == -1) { /* Throw an exception */ LOGE("Cannot open port"); /* TODO: throw an exception */ return NULL; } } /* Configure device */ { struct termios cfg; LOGD("Configuring serial port"); if (tcgetattr(fd, &cfg)) { LOGE("tcgetattr() failed"); close(fd); /* TODO: throw an exception */ return NULL; } cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { LOGE("tcsetattr() failed"); close(fd); /* TODO: throw an exception */ return NULL; } } /* Create a corresponding file descriptor */ { jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor"); jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V"); jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I"); mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor); (*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd); } return mFileDescriptor; }
/*! \brief Open the serial port \param Device : Port name (COM1, COM2, ... for Windows ) or (/dev/ttyS0, /dev/ttyACM0, /dev/ttyUSB0 ... for linux) \param Bauds : Baud rate of the serial port. \n Supported baud rate for Windows : - 110 - 300 - 600 - 1200 - 2400 - 4800 - 9600 - 14400 - 19200 - 38400 - 56000 - 57600 - 115200 - 128000 - 256000 \n Supported baud rate for Linux :\n - 110 - 300 - 600 - 1200 - 2400 - 4800 - 9600 - 19200 - 38400 - 57600 - 115200 \return 1 success \return -1 device not found \return -2 error while opening the device \return -3 error while getting port parameters \return -4 Speed (Bauds) not recognized \return -5 error while writing port parameters \return -6 error while writing timeout parameters */ char serialib::Open(const char *Device,const unsigned int Bauds) { #if defined (_WIN32) || defined( _WIN64) // Open serial port hSerial = CreateFileA( Device,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if(hSerial==INVALID_HANDLE_VALUE) { if(GetLastError()==ERROR_FILE_NOT_FOUND) return -1; // Device not found return -2; // Error while opening the device } // Set parameters DCB dcbSerialParams = {0}; // Structure for the port parameters dcbSerialParams.DCBlength=sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) // Get the port parameters return -3; // Error while getting port parameters switch (Bauds) // Set the speed (Bauds) { case 110 : dcbSerialParams.BaudRate=CBR_110; break; case 300 : dcbSerialParams.BaudRate=CBR_300; break; case 600 : dcbSerialParams.BaudRate=CBR_600; break; case 1200 : dcbSerialParams.BaudRate=CBR_1200; break; case 2400 : dcbSerialParams.BaudRate=CBR_2400; break; case 4800 : dcbSerialParams.BaudRate=CBR_4800; break; case 9600 : dcbSerialParams.BaudRate=CBR_9600; break; case 14400 : dcbSerialParams.BaudRate=CBR_14400; break; case 19200 : dcbSerialParams.BaudRate=CBR_19200; break; case 38400 : dcbSerialParams.BaudRate=CBR_38400; break; case 56000 : dcbSerialParams.BaudRate=CBR_56000; break; case 57600 : dcbSerialParams.BaudRate=CBR_57600; break; case 115200 : dcbSerialParams.BaudRate=CBR_115200; break; case 128000 : dcbSerialParams.BaudRate=CBR_128000; break; case 256000 : dcbSerialParams.BaudRate=CBR_256000; break; default : return -4; } dcbSerialParams.ByteSize=8; // 8 bit data dcbSerialParams.StopBits=ONESTOPBIT; // One stop bit dcbSerialParams.Parity=NOPARITY; // No parity if(!SetCommState(hSerial, &dcbSerialParams)) // Write the parameters return -5; // Error while writing // Set TimeOut timeouts.ReadIntervalTimeout=0; // Set the Timeout parameters timeouts.ReadTotalTimeoutConstant=MAXDWORD; // No TimeOut timeouts.ReadTotalTimeoutMultiplier=0; timeouts.WriteTotalTimeoutConstant=MAXDWORD; timeouts.WriteTotalTimeoutMultiplier=0; if(!SetCommTimeouts(hSerial, &timeouts)) // Write the parameters return -6; // Error while writting the parameters return 1; // Opening successfull #endif #ifdef __linux__ struct termios options; // Structure with the device's options // Open device fd = open(Device, O_RDWR | O_NOCTTY | O_NDELAY); // Open port if (fd == -1) return -2; // If the device is not open, return -1 fcntl(fd, F_SETFL, FNDELAY); // Open the device in nonblocking mode // Set parameters tcgetattr(fd, &options); // Get the current options of the port bzero(&options, sizeof(options)); // Clear all the options speed_t Speed; switch (Bauds) // Set the speed (Bauds) { case 110 : Speed=B110; break; case 300 : Speed=B300; break; case 600 : Speed=B600; break; case 1200 : Speed=B1200; break; case 2400 : Speed=B2400; break; case 4800 : Speed=B4800; break; case 9600 : Speed=B9600; break; case 19200 : Speed=B19200; break; case 38400 : Speed=B38400; break; case 57600 : Speed=B57600; break; case 115200 : Speed=B115200; break; default : return -4; } cfsetispeed(&options, Speed); // Set the baud rate at 115200 bauds cfsetospeed(&options, Speed); options.c_cflag |= ( CLOCAL | CREAD | CS8); // Configure the device : 8 bits, no parity, no control options.c_iflag |= ( IGNPAR | IGNBRK ); options.c_cc[VTIME]=0; // Timer unused options.c_cc[VMIN]=0; // At least on character before satisfy reading tcsetattr(fd, TCSANOW, &options); // Activate the settings return (1); // Success #endif }
/* return icom error */ static int icoms_set_ser_port( icoms *p, flow_control fc, baud_rate baud, parity parity, stop_bits stop, word_length word ) { int rv; struct termios tio; speed_t speed = 0; a1logd(p->log, 8, "icoms_set_ser_port: About to set port characteristics:\n" " Port name = %s\n" " Flow control = %d\n" " Baud Rate = %d\n" " Parity = %d\n" " Stop bits = %d\n" " Word length = %d\n" ,p->name ,fc ,baud ,parity ,stop ,word); if (p->is_open) /* Close it and re-open it */ p->close_port(p); if (p->port_type(p) == icomt_serial) { a1logd(p->log, 8, "icoms_set_ser_port: Make sure serial port is open\n"); if (fc != fc_nc) p->fc = fc; if (baud != baud_nc) p->br = baud; if (parity != parity_nc) p->py = parity; if (stop != stop_nc) p->sb = stop; if (word != length_nc) p->wl = word; /* Make sure the port is open */ if (!p->is_open) { a1logd(p->log, 8, "icoms_set_ser_port: about to open serial port '%s'\n",p->spath); if ((p->fd = open(p->spath, O_RDWR | O_NOCTTY )) < 0) { a1logd(p->log, 1, "icoms_set_ser_port: open port '%s' failed with %d (%s)\n",p->spath,p->fd,strerror(errno)); return ICOM_SYS; } /* O_NONBLOCK O_SYNC */ p->is_open = 1; } if ((rv = tcgetattr(p->fd, &tio)) < 0) { a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: tcgetattr on '%s' failed with %d (%s)\n",p->spath,p->fd,strerror(errno)); return ICOM_SYS; } /* Clear everything in the tio, and just set what we want */ memset(&tio, 0, sizeof(struct termios)); /* Turn on basic configuration: */ tio.c_iflag |= ( IGNBRK /* Ignore Break */ ); tio.c_oflag |= ( 0 ); tio.c_cflag |= ( CREAD /* Enable the receiver */ | CLOCAL /* Ignore modem control lines */ ); tio.c_lflag |= ( 0 /* Non-canonical input mode */ ); /* And configure: */ tio.c_cc[VTIME] = 1; /* 0.1 second timeout */ tio.c_cc[VMIN] = 64; /* Comfortably less than _PF_MAX_INPUT */ switch (p->fc) { case fc_nc: close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: illegal flow control %d\n",p->fc); return ICOM_SYS; case fc_XonXOff: /* Use Xon/Xoff bi-directional flow control */ tio.c_iflag |= IXON; /* Enable XON/XOFF flow control on output */ tio.c_iflag |= IXOFF; /* Enable XON/XOFF flow control on input */ tio.c_cc[VSTART] = 0x11; /* ^Q */ tio.c_cc[VSTOP] = 0x13; /* ^S */ break; case fc_Hardware: /* Use RTS/CTS bi-directional flow control */ #ifdef __APPLE__ tio.c_cflag |= CCTS_OFLOW; tio.c_cflag |= CRTS_IFLOW; #else tio.c_cflag |= CRTSCTS; #endif break; case fc_HardwareDTR: /* Use DTR/DSR bi-directional flow control */ #ifdef __APPLE__ tio.c_cflag |= CDSR_OFLOW; tio.c_cflag |= CDTR_IFLOW; #else #ifdef CDTRDSR /* Hmm. Not all Linux's support this... */ tio.c_cflag |= CDTRDSR; #endif #endif break; default: break; } switch (p->py) { case parity_nc: close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: illegal parity setting %d\n",p->py); return ICOM_SYS; break; case parity_none: tio.c_iflag &= ~INPCK; /* Disable input parity checking */ break; case parity_odd: tio.c_iflag |= INPCK; /* Enable input parity checking */ tio.c_cflag |= PARENB; /* Enable input and output parity checking */ tio.c_cflag |= PARODD; /* Input and output parity is odd */ break; case parity_even: tio.c_iflag |= INPCK; /* Enable input parity checking */ tio.c_cflag |= PARENB; /* Enable input and output parity checking */ break; } switch (p->sb) { case stop_nc: close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: illegal stop bits %d\n",p->sb); return ICOM_SYS; case stop_1: break; /* defaults to 1 */ case stop_2: tio.c_cflag |= CSTOPB; break; } switch (p->wl) { case length_nc: close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: illegal word length %d\n",p->wl); return ICOM_SYS; case length_5: tio.c_cflag |= CS5; break; case length_6: tio.c_cflag |= CS6; break; case length_7: tio.c_cflag |= CS7; break; case length_8: tio.c_cflag |= CS8; break; } /* Set the baud rate */ switch (p->br) { case baud_110: speed = B110; break; case baud_300: speed = B300; break; case baud_600: speed = B600; break; case baud_1200: speed = B1200; break; case baud_2400: speed = B2400; break; case baud_4800: speed = B4800; break; case baud_9600: speed = B9600; break; case baud_19200: speed = B19200; break; case baud_38400: speed = B38400; break; case baud_57600: speed = B57600; break; case baud_115200: speed = B115200; break; case baud_921600: speed = B921600; break; default: close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: illegal baud rate! (0x%x)\n",p->br); return ICOM_SYS; } tcflush(p->fd, TCIOFLUSH); /* Discard any current in/out data */ #ifdef NEVER // for osx >= 10.4 ? or >= 10.3 ?? // Doesn't actually seem to be needed... ?? if (speed > B115200) { if (ioctl(p->fd, IOSSIOSPEED, &speed ) == -1) printf( "Error %d calling ioctl( ..., IOSSIOSPEED, ... )\n", errno ); } #endif if ((rv = cfsetispeed(&tio, speed)) < 0) { close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: cfsetispeed failed with '%s'\n", strerror(errno)); return ICOM_SYS; } if ((rv = cfsetospeed(&tio, speed)) < 0) { close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: cfsetospeed failed with '%s'\n", strerror(errno)); return ICOM_SYS; } /* Make change immediately */ if ((rv = tcsetattr(p->fd, TCSANOW, &tio)) < 0) { close(p->fd); a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: tcsetattr failed with '%s'\n", strerror(errno)); return ICOM_SYS; } tcflush(p->fd, TCIOFLUSH); /* Discard any current in/out data */ p->write = icoms_ser_write; p->read = icoms_ser_read; } a1logd(p->log, 8, "icoms_set_ser_port: port characteristics set ok\n"); return ICOM_OK; }
int _setup_port(int baud, int data_bits, int stop_bits, int parity, int hardware_control) { // Check file descriptor if(!isatty(fd)) { fprintf(stderr, "\nERROR: file descriptor %d is NOT a serial port\n", fd); return 0; } // Read file descritor configuration struct termios config; if(tcgetattr(fd, &config) < 0) { fprintf(stderr, "\nERROR: could not read configuration of fd %d\n", fd); return 0; } // Input flags - Turn off input processing // convert break to null byte, no CR to NL translation, // no NL to CR translation, don't mark parity errors or breaks // no input parity check, don't strip high bit off, // no XON/XOFF software flow control config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); // Output flags - Turn off output processing // no CR to NL translation, no NL to CR-NL translation, // no NL to CR translation, no column 0 CR suppression, // no Ctrl-D suppression, no fill characters, no case mapping, // no local output processing config.c_oflag &= ~(OCRNL | ONLCR | ONLRET | ONOCR | OFILL | OPOST); #ifdef OLCUC config.c_oflag &= ~OLCUC; #endif #ifdef ONOEOT config.c_oflag &= ~ONOEOT; #endif // No line processing: // echo off, echo newline off, canonical mode off, // extended input processing off, signal chars off config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); // Turn off character processing // clear current char size mask, no parity checking, // no output processing, force 8 bit input config.c_cflag &= ~(CSIZE | PARENB); config.c_cflag |= CS8; // One input byte is enough to return from read() // Inter-character timer off config.c_cc[VMIN] = 1; config.c_cc[VTIME] = 10; // was 0 // Get the current options for the port ////struct termios options; ////tcgetattr(fd, &options); // Apply baudrate switch (baud) { case 1200: if (cfsetispeed(&config, B1200) < 0 || cfsetospeed(&config, B1200) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return 0; } break; case 1800: cfsetispeed(&config, B1800); cfsetospeed(&config, B1800); break; case 9600: cfsetispeed(&config, B9600); cfsetospeed(&config, B9600); break; case 19200: cfsetispeed(&config, B19200); cfsetospeed(&config, B19200); break; case 38400: if (cfsetispeed(&config, B38400) < 0 || cfsetospeed(&config, B38400) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return 0; } break; case 57600: if (cfsetispeed(&config, B57600) < 0 || cfsetospeed(&config, B57600) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return 0; } break; case 115200: if (cfsetispeed(&config, B115200) < 0 || cfsetospeed(&config, B115200) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return 0; } break; // These two non-standard (by the 70'ties ) rates are fully supported on // current Debian and Mac OS versions (tested since 2010). case 460800: if (cfsetispeed(&config, B460800) < 0 || cfsetospeed(&config, B460800) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return 0; } break; case 921600: if (cfsetispeed(&config, B921600) < 0 || cfsetospeed(&config, B921600) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return 0; } break; default: fprintf(stderr, "ERROR: Desired baud rate %d could not be set, aborting.\n", baud); return 0; break; } // Finally, apply the configuration if(tcsetattr(fd, TCSAFLUSH, &config) < 0) { fprintf(stderr, "\nERROR: could not set configuration of fd %d\n", fd); return 0; } // Done! return 1; }
int test_pwren(int argc, char *argv[]) { printf ("\nSensor power disabled. You should now see sensor data capture errors.\n\n"); usleep(3000000) ; stm32_gpiowrite(SENSOR_PWR_EN,0); usleep(100000) ; stm32_gpiowrite(SENSOR_PWR_EN,1); usleep(300000) ; printf ("\nSensor power enabled. Data capture errors should now stop.\n\n"); usleep(4000000) ; int fd; /* File descriptor for the port */ char c; /*GPS is connected to the controller via UART2 and the port for uart 2 is /dev/ttyS1 */ fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);/*Opening the port */ /* Try to set baud rate */ struct termios uart_config; tcgetattr(fd, &uart_config); // get what is the current baud rate /* Setting baud rate of UART to 9600 for communicating with GPS at its default baudrate of 9600 */ cfsetispeed(&uart_config, B9600); cfsetospeed(&uart_config, B9600); tcsetattr(fd, TCSANOW, &uart_config); //confirming that the baud rate is set int i=0,n=0; struct pollfd fds; fds.fd = fd; fds.events = POLLIN; printf ("\nPrinting GPS data...\n") ; usleep(2000000) ; while (i<1000) { if (i == 500) { printf ("\nGPS Power Disabled. You should see no data for next 5 seconds.\n") ; stm32_gpiowrite(GPS_PWR_EN,0); usleep(5000000); stm32_gpiowrite(GPS_PWR_EN,1); printf ("\nGPS Power Enabled. You should see the GPS data now.\n") ; usleep(2000000) ; } if (poll(&fds, 1, 1000)>0) { n=read(fd,&c,1); // reading and printing the characters coming from GPS to ensure the connection with gps if (n<0) return -1 ; printf("%c ",c); // printing the characters on console } i++; } close(fd); printf ("\n\nGPS POWER ENABLE and SENSOR POWER ENABLE Testing Complete.\n\n"); return 0 ; }