/* * Copyright (c) 2001 by Cliff Green. All rights reserved. Individual files * may be covered by other copyrights (as noted in the file itself). * * Redistribution and use in source and binary forms are permitted * provided that this entire copyright notice is duplicated in all such * copies. * * This software is provided "as is" and without any expressed or implied * warranties, including, without limitation, the implied warranties of * merchantibility and fitness for any particular purpose. */ //---------------------------------------------------------------------- // Source file: serialcommunix.cpp // Written by: Cliff Green, 2001 // Compiler: Metrowerks CodeWarrior Pro 6 // History: // Modified: 8/08/2001 // By: Cliff Green // Comments: See header file. //---------------------------------------------------------------------- #include "serialcommunix.h" #include // termios and unix read / write stuff #include #include #include namespace { const char STX(0x02); const char ETX(0x03); } namespace Util { SerialCommUnix::SerialCommUnix (const char* devName) : mFd(0), mOrigIos() { mFd = open (devName, O_RDWR | O_NOCTTY); if (mFd < 0) { throw std::invalid_argument(std::string("Error opening: ") + devName); } if (!tty_raw()) { throw std::invalid_argument(std::string("Error setting port to raw: ") + devName); } } SerialCommUnix::~SerialCommUnix() { close (mFd); } bool SerialCommUnix::transmit (const BinaryBuf<>& buf) const { // wrap STX and ETX around the packet std::string strBuf (STX + toHex(buf) + ETX); /* // Original code - send all data in one write int num = write (mFd, buf.data(), buf.length()); return num == buf.length(); */ for (std::string::size_type i (0); i < strBuf.length(); ++i) { if (write (mFd, &strBuf[i], 1) != 1) { return false; } } return true; } const BinaryBuf<> SerialCommUnix::receive () const { char c (0); while (c != STX) { int num = read (mFd, &c, 1); } std::string newBuf; while (c != ETX) { int num = read (mFd, &c, 1); if (c != ETX) { newBuf += c; } if (c == STX) { // ETX somehow got dropped, start over newBuf.clear(); } } return fromHex(newBuf); } bool SerialCommUnix::tty_raw () { termios buf; if (tcgetattr(mFd, &mOrigIos) < 0) { return false; } buf = mOrigIos; buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); buf.c_cflag &= ~(CSIZE | PARENB); buf.c_cflag |= CS8; buf.c_oflag &= ~(OPOST); buf.c_cc[VMIN] = 1; // 1 byte at a time, no timer buf.c_cc[VTIME] = 0; if (cfsetispeed (&buf, B19200) < 0) { return false; } if (cfsetospeed (&buf, B19200) < 0) { return false; } if (tcsetattr(mFd, TCSAFLUSH, &buf) < 0) { return false; } return true; } bool SerialCommUnix::tty_reset () { if (tcsetattr(mFd, TCSAFLUSH, &mOrigIos) < 0) { return false; } return true; } } // end namespace