/* * wiringSerial.c: * Handle a serial port *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ * * wiringPi is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * wiringPi is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with wiringPi. If not, see . *********************************************************************** */ #include #include #include #include #include #include #include #include #include #include #include #include "wiringSerial.h" /* * serialOpen: * Open and initialise the serial port, setting port parameters ********************************************************************************* */ int serialOpen (const char *device, const int baud) { struct termios options; speed_t myBaud; int status, fd; int regularFile = 0; switch (baud) { case 50: myBaud = B50; break; case 75: myBaud = B75; break; case 110: myBaud = B110; break; case 134: myBaud = B134; break; case 150: myBaud = B150; break; case 200: myBaud = B200; break; case 300: myBaud = B300; break; case 600: myBaud = B600; break; case 1200: myBaud = B1200; break; case 1800: myBaud = B1800; break; case 2400: myBaud = B2400; break; case 4800: myBaud = B4800; break; case 9600: myBaud = B9600; break; case 19200: myBaud = B19200; break; case 38400: myBaud = B38400; break; case 57600: myBaud = B57600; break; case 115200: myBaud = B115200; break; case 230400: myBaud = B230400; break; case 460800: myBaud = B460800; break; case 500000: myBaud = B500000; break; case 576000: myBaud = B576000; break; case 921600: myBaud = B921600; break; case 1000000: myBaud = B1000000; break; case 1152000: myBaud = B1152000; break; case 1500000: myBaud = B1500000; break; case 2000000: myBaud = B2000000; break; case 2500000: myBaud = B2500000; break; case 3000000: myBaud = B3000000; break; case 3500000: myBaud = B3500000; break; case 4000000: myBaud = B4000000; break; // Undocumented: If baud is -1, treat device as a regular file! case -1: myBaud = B115200; regularFile = 1; break; default: return -2; } if (!regularFile) { if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) return -1; fcntl (fd, F_SETFL, O_RDWR); // Get and modify current options: tcgetattr (fd, &options); cfmakeraw (&options); cfsetispeed (&options, myBaud); cfsetospeed (&options, myBaud); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; options.c_cc [VMIN] = 0; options.c_cc [VTIME] = 100; // Ten seconds (100 deciseconds) tcsetattr (fd, TCSANOW, &options); ioctl (fd, TIOCMGET, &status); status |= TIOCM_DTR; status |= TIOCM_RTS; ioctl (fd, TIOCMSET, &status); usleep (10000); // 10mS } else { // Want to open a regular file if ((fd = open (device, O_RDWR | O_CREAT, 0666)) == -1) return -1; } return fd; } /* * serialFlush: * Flush the serial buffers (both tx & rx) ********************************************************************************* */ void serialFlush (const int fd) { tcflush (fd, TCIOFLUSH); } /* * serialClose: * Release the serial port ********************************************************************************* */ void serialClose (const int fd) { close (fd); } /* * serialPutchar: * Send a single character to the serial port ********************************************************************************* */ void serialPutchar (const int fd, const unsigned char c) { write (fd, &c, 1); } /* * serialPuts: * Send a string to the serial port ********************************************************************************* */ void serialPuts (const int fd, const char *s) { write (fd, s, strlen (s)); } /* * serialPrintf: * Printf over Serial ********************************************************************************* */ void serialPrintf (const int fd, const char *message, ...) { va_list argp; char buffer [1024]; va_start (argp, message); vsnprintf (buffer, 1023, message, argp); va_end (argp); serialPuts (fd, buffer); } /* * serialDataAvail: * Return the number of bytes of data avalable to be read in the serial port ********************************************************************************* */ int serialDataAvail (const int fd) { int result; if (ioctl (fd, FIONREAD, &result) == -1) return -1; return result; } /* * serialGetchar: * Get a single character from the serial device. * Note: Zero is a valid character and this function will time-out after * 10 seconds. ********************************************************************************* */ int serialGetchar (const int fd) { uint8_t x; if (read (fd, &x, 1) != 1) return -1; return ((int)x) & 0xFF; }