00001 /*!@file Devices/Serial.C class for interfacing with a serial port */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Nitin Dhavale <dhavale@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/Serial.C $ 00035 // $Id: Serial.C 14056 2010-09-28 00:12:03Z rand $ 00036 // 00037 00038 #include "Devices/Serial.H" 00039 #include "Util/Timer.H" 00040 #include "Component/OptionManager.H" 00041 #include "Util/log.H" 00042 #include "rutz/unixcall.h" // for rutz::unixcall::get_file_user_pid() 00043 #include <iostream> 00044 #include <sys/types.h> 00045 #include <dirent.h> 00046 #include <unistd.h> 00047 00048 const ModelOptionCateg MOC_Serial= { 00049 MOC_SORTPRI_3, "Serial Port Related Options" }; 00050 00051 const ModelOptionDef OPT_DevName = 00052 { MODOPT_ARG(std::string), "DevName", &MOC_Serial, OPTEXP_CORE, 00053 "Device file", 00054 "serial-dev", '\0', "", "/dev/ttyUSB0" }; 00055 00056 // ###################################################################### 00057 00058 Serial::Serial(OptionManager& mgr, 00059 const std::string& descrName, 00060 const std::string& tagName) : 00061 ModelComponent(mgr, descrName, tagName), 00062 itsCmdDevName(&OPT_DevName, this, 0), 00063 itsDeviceDescription(tagName+"DeviceDescription", this, ""), 00064 itsSearchPrefix(tagName+"SearchPrefix", this, "ttyUSB"), 00065 itsBaud(tagName+"Baud", this, 9600), 00066 itsCharBits(tagName+"CharBits", this, 8), 00067 itsStopBits(tagName+"StopBits", this, 1), 00068 itsUseParity(tagName+"UseParity", this, false), 00069 itsParityOdd(tagName+"ParityOdd", this, false), 00070 itsFlowHard(tagName+"FlowHard", this, false), 00071 itsFlowSoft(tagName+"FlowSoft", this, false), 00072 itsRdTout(tagName+"ReadTimeout", this, 0), 00073 itsBlocking(tagName+"Blocking", this, true), 00074 itsSerialOk(tagName+"SerialOk", this, false), 00075 dev(-1), 00076 itsDevName(""), 00077 serialErrno(serialErrSuccess) 00078 { 00079 00080 } 00081 00082 // ###################################################################### 00083 void Serial::start2() 00084 { 00085 //Check to see if we have a hardcoded device name. If so, then let's just 00086 //go ahead and enable that port. If 00087 LINFO("Looking Device Name [%s]",itsDevName.c_str()); 00088 if(itsDevName != "") 00089 { 00090 LINFO("Opening %s", itsDevName.c_str()); 00091 enablePort(itsDevName); 00092 } else if (itsDevName == "search") { 00093 LINFO("Searching for devices"); 00094 itsCmdDevName.setVal(""); 00095 00096 DIR *directory_p; 00097 struct dirent *entry_p; 00098 00099 //Open the device directory to search for devices whose names match the search prefix 00100 directory_p = ::opendir ("/dev"); 00101 if (directory_p == NULL) 00102 LFATAL("Could Not Open /dev Directory!"); 00103 00104 //Iterate through the directory entries 00105 while ((entry_p = ::readdir (directory_p))) 00106 { 00107 std::string entryName(entry_p->d_name); 00108 if(entryName.find(itsSearchPrefix.getVal().c_str()) != std::string::npos) 00109 {//If the directory entry name matches our search prefix, then let's try configuring a serial 00110 //port on that device, sending it an identity request command (0x00), and comparing the result 00111 //with our required device description 00112 00113 enablePort("/dev/" + entryName); 00114 unsigned char cmd[1] = {0}; 00115 00116 write(cmd,1); 00117 std::vector<unsigned char> deviceStringVec = readFrame(cmd[0], 255); 00118 00119 std::string deviceString(deviceStringVec.begin(), deviceStringVec.end()); 00120 LINFO("%s : %s", entryName.c_str(), deviceString.c_str()); 00121 00122 if(deviceString == itsDeviceDescription.getVal()) 00123 { 00124 itsCmdDevName.setVal("/dev/"+entryName); 00125 break; 00126 } 00127 } 00128 00129 00130 } 00131 (void) ::closedir (directory_p); 00132 if(itsCmdDevName.getVal() == "") 00133 { 00134 LFATAL("Could Not Find Serial Device Matching Descriptor (%s)", itsDeviceDescription.getVal().c_str()); 00135 } 00136 } else { 00137 LINFO("Opening from cmd line %s", itsCmdDevName.getVal().c_str()); 00138 enablePort(itsCmdDevName.getVal()); 00139 } 00140 } 00141 00142 00143 // ###################################################################### 00144 void Serial::enablePort(std::string DeviceName) 00145 { 00146 closePort(); 00147 serialErrno = serialErrSuccess; // clear the error flag 00148 00149 openPort(DeviceName); // open the device 00150 perror(); 00151 00152 setSpeed(itsBaud.getVal()); // Set the baud rate 00153 perror(); 00154 00155 setFlowControl(itsFlowHard.getVal(), 00156 itsFlowSoft.getVal()); // Set flow control 00157 perror(); 00158 00159 setCharBits(itsCharBits.getVal()); // set no of bits in a char 00160 perror(); 00161 00162 setParity(itsUseParity.getVal(), 00163 itsParityOdd.getVal()); // Set even or odd parity 00164 perror(); 00165 00166 setBlocking(itsBlocking.getVal()); // blocking mode? 00167 perror(); 00168 } 00169 00170 00171 #include <cstdio> 00172 // ###################################################################### 00173 void Serial::stop2() 00174 { 00175 closePort(); 00176 } 00177 00178 // ###################################################################### 00179 void Serial::closePort() 00180 { 00181 if(dev >= 0) { 00182 //sendBreak(); 00183 close(dev); 00184 dev = -1; } 00185 } 00186 00187 // ###################################################################### 00188 void Serial::configureSearch(const std::string DeviceDescription, const int speed, const std::string SearchPrefix, const char *format, 00189 const bool flowSoft, const bool flowHard, 00190 const int tout) 00191 { 00192 LINFO("Search for %s in speed %d",DeviceDescription.c_str(),speed); 00193 itsDevName = "search"; 00194 itsDeviceDescription.setVal(DeviceDescription); 00195 itsSearchPrefix.setVal(SearchPrefix); 00196 //enable serch 00197 //configure("search", speed, format, flowSoft, flowHard, tout); 00198 //Bypass search 00199 configure("", speed, format, flowSoft, flowHard, tout); 00200 } 00201 00202 // ###################################################################### 00203 void Serial::configure(const char *dev, const int speed, const char *format, 00204 const bool flowSoft, const bool flowHard, 00205 const int tout) 00206 { 00207 itsDevName = dev; 00208 00209 00210 itsBaud.setVal(speed); 00211 itsFlowSoft.setVal(flowSoft); 00212 itsFlowHard.setVal(flowHard); 00213 itsRdTout.setVal(tout); 00214 00215 if (strlen(format) != 3) LFATAL("Incorrect format string: %s", format); 00216 00217 switch(format[0]) { 00218 case '5': itsCharBits.setVal(5); break; 00219 case '6': itsCharBits.setVal(6); break; 00220 case '7': itsCharBits.setVal(7); break; 00221 case '8': itsCharBits.setVal(8); break; 00222 default: LFATAL("Invalid charbits: %c (should be 5..8)", format[0]); 00223 } 00224 00225 switch(format[1]) { 00226 case 'N': itsUseParity.setVal(false); break; 00227 case 'E': itsUseParity.setVal(true); itsParityOdd.setVal(false); break; 00228 case 'O': itsUseParity.setVal(true); itsParityOdd.setVal(true); break; 00229 default: LFATAL("Invalid parity: %c (should be N,E,O)", format[1]); 00230 } 00231 00232 switch(format[2]) { 00233 case '1': itsStopBits.setVal(1); break; 00234 case '2': itsStopBits.setVal(2); break; 00235 default: LFATAL("Invalid stopbits: %c (should be 1..2)", format[2]); 00236 } 00237 } 00238 00239 // ###################################################################### 00240 serialError Serial::setSpeed(const int speed) 00241 { 00242 struct termios options; 00243 unsigned int rate; 00244 00245 switch(speed) 00246 { 00247 case 230400: 00248 rate = B230400; 00249 break; 00250 case 115200: 00251 rate = B115200; 00252 break; 00253 case 57600: 00254 rate = B57600; 00255 break; 00256 case 38400: 00257 rate = B38400; 00258 break; 00259 case 19200: 00260 rate = B19200; 00261 break; 00262 case 9600: 00263 rate = B9600; 00264 break; 00265 case 4800: 00266 rate = B4800; 00267 break; 00268 case 2400: 00269 rate = B2400; 00270 break; 00271 case 1200: 00272 rate = B1200; 00273 break; 00274 case 600: 00275 rate = B600; 00276 break; 00277 case 300: 00278 rate = B300; 00279 break; 00280 case 110: 00281 rate = B110; 00282 break; 00283 case 0: 00284 rate = B0; 00285 break; 00286 default: 00287 return serialError(serialErrSpeedInvalid); 00288 } 00289 00290 // get current options 00291 if(tcgetattr(dev, &options)==-1){ 00292 serialErrno = serialErrTcGetAttrFailed; 00293 return serialErrno; 00294 } 00295 00296 // set the speed 00297 cfsetispeed(&options, rate); 00298 cfsetospeed(&options, rate); 00299 00300 // change the terminals parameter instantly 00301 if( tcsetattr(dev, TCSANOW, &options) == -1){ 00302 serialErrno = serialErrTcSetAttrFailed; 00303 return serialErrno; 00304 } 00305 00306 if( tcgetattr(dev, &options) == -1) { 00307 serialErrno = serialErrTcGetAttrFailed; 00308 return serialErrno; 00309 } 00310 00311 // update our ModelParam: 00312 itsBaud.setVal(speed); 00313 00314 return serialErrSuccess; 00315 } 00316 00317 00318 // ###################################################################### 00319 serialError Serial::setFlowControl(const bool useHard, const bool useSoft) 00320 { 00321 termios options; 00322 00323 if( tcgetattr(dev, &options) == -1){ 00324 serialErrno = serialErrTcGetAttrFailed; 00325 return serialErrno; 00326 } 00327 00328 options.c_cflag &= ~CRTSCTS; 00329 options.c_iflag &= ~(IXON | IXANY | IXOFF); 00330 00331 if (useSoft) options.c_iflag |= (IXON | IXANY | IXOFF); 00332 if (useHard) options.c_cflag |= CRTSCTS; 00333 00334 if(tcsetattr(dev, TCSANOW, &options) == -1){ 00335 serialErrno = serialErrTcGetAttrFailed; 00336 return serialErrno; 00337 } 00338 00339 // update our ModelParams: 00340 itsFlowHard.setVal(useHard); 00341 itsFlowSoft.setVal(useSoft); 00342 00343 return serialErrSuccess; 00344 } 00345 00346 // ###################################################################### 00347 serialError Serial::setCharBits(const int bits) 00348 { 00349 termios options; 00350 00351 if(tcgetattr(dev, &options)==-1){ 00352 serialErrno = serialErrTcGetAttrFailed; 00353 return serialErrno; 00354 } 00355 00356 options.c_cflag &= ~CSIZE; // mask off the 'size' bits 00357 00358 switch(bits) 00359 { 00360 case 5: options.c_cflag |= CS5; break; 00361 case 6: options.c_cflag |= CS6; break; 00362 case 7: options.c_cflag |= CS7; break; 00363 case 8: options.c_cflag |= CS8; break; 00364 default: return serialError(serialErrCharsizeInvalid); 00365 } 00366 00367 if( tcsetattr(dev, TCSANOW, &options) == -1 ){ 00368 serialErrno = serialErrTcSetAttrFailed; 00369 return serialErrno; 00370 } 00371 00372 // update our ModelParam: 00373 itsCharBits.setVal(bits); 00374 00375 return serialErrSuccess; 00376 } 00377 00378 // ###################################################################### 00379 serialError Serial::setParity(const bool useParity, const bool oddParity) 00380 { 00381 struct termios options; 00382 00383 if(tcgetattr(dev, &options)==-1){ 00384 serialErrno = serialErrTcGetAttrFailed; 00385 return serialErrno; 00386 } 00387 00388 options.c_cflag &= ~(PARENB | PARODD); 00389 if (useParity) 00390 { 00391 if (oddParity) 00392 options.c_cflag |= (PARENB | PARODD); 00393 else 00394 options.c_cflag |= PARENB; 00395 } 00396 00397 if(tcsetattr(dev, TCSANOW, &options) == -1){ 00398 serialErrno = serialErrTcSetAttrFailed; 00399 return serialErrno; 00400 } 00401 00402 // update our ModelParams: 00403 itsUseParity.setVal(useParity); 00404 itsParityOdd.setVal(oddParity); 00405 00406 return serialErrSuccess; 00407 } 00408 00409 // ###################################################################### 00410 serialError Serial::setStopBits(const int bits) 00411 { 00412 struct termios options; 00413 00414 if(tcgetattr(dev, &options)==-1){ 00415 serialErrno = serialErrTcGetAttrFailed; 00416 return serialErrno; 00417 } 00418 00419 options.c_cflag &= ~CSTOPB; 00420 if (bits == 2) options.c_cflag |= CSTOPB; 00421 else if (bits != 1) return serialError(serialErrStopbitsInvalid); 00422 00423 if(tcsetattr(dev, TCSANOW, &options) == -1){ 00424 serialErrno = serialErrTcSetAttrFailed; 00425 return serialErrno; 00426 } 00427 00428 // update our ModelParam: 00429 itsStopBits.setVal(bits); 00430 00431 return serialErrSuccess; 00432 } 00433 00434 // ###################################################################### 00435 serialError Serial::setBlocking(const bool blocking) 00436 { 00437 int flags = fcntl(dev, F_GETFL, 0); 00438 if (flags == -1) PLERROR("Cannot get flags"); 00439 if (blocking) flags &= (~O_NONBLOCK); else flags |= O_NONBLOCK; 00440 if (fcntl(dev, F_SETFL, flags) == -1) PLERROR("Cannot set flags"); 00441 00442 itsBlocking.setVal(blocking); 00443 00444 return serialErrSuccess; 00445 } 00446 00447 // ###################################################################### 00448 void Serial::toggleDTR(const time_t ms) 00449 { 00450 struct termios tty, old; 00451 if(tcgetattr(dev, &tty) == -1 || tcgetattr(dev, &old) == -1){ 00452 serialErrno = serialErrTcGetAttrFailed; 00453 } 00454 00455 cfsetospeed(&tty, B0); 00456 cfsetispeed(&tty, B0); 00457 00458 if(tcsetattr(dev, TCSANOW, &tty) == -1){ 00459 serialErrno = serialErrTcSetAttrFailed; 00460 } 00461 00462 if(ms) 00463 usleep(ms*1000); 00464 00465 if(tcsetattr(dev, TCSANOW, &old) == -1){ 00466 serialErrno = serialErrTcSetAttrFailed; 00467 } 00468 } 00469 00470 // ###################################################################### 00471 void Serial::sendBreak(void) 00472 { 00473 // Send a Hangup to the port 00474 tcsendbreak(dev, 0); 00475 } 00476 00477 // ###################################################################### 00478 serialError Serial::error(const serialError serialErrorNum) 00479 { 00480 serialErrno = serialErrorNum; 00481 return serialErrorNum; 00482 } 00483 00484 // ###################################################################### 00485 int Serial::openPort(std::string DeviceName) 00486 { 00487 const pid_t fuser = 00488 rutz::unixcall::get_file_user_pid(DeviceName.c_str()); 00489 00490 if (fuser != 0 && DeviceName.compare("/dev/null") != 0) 00491 { 00492 LINFO("serial device %s is already in use by process pid=%d;\n" 00493 "\ttry using /dev/null or a different serial device instead", 00494 DeviceName.c_str(), int(fuser)); 00495 } 00496 00497 int flags= O_RDWR | O_NOCTTY; 00498 termios options; 00499 00500 // don't set the flag if we are setting a timeout on 00501 // the descriptor 00502 if (itsRdTout.getVal() < 0) flags |= O_NDELAY; 00503 00504 CLDEBUG("Opening port %s", DeviceName.c_str()); 00505 dev = ::open(DeviceName.c_str(), flags); 00506 if (dev == -1) { serialErrno = serialErrOpenFailed; return dev; } 00507 LDEBUG("Done"); 00508 00509 // Save current state 00510 if( tcgetattr(dev, &savedState) == -1 ){ 00511 serialErrno = serialErrTcGetAttrFailed; 00512 return -1; 00513 } 00514 00515 // reset all the flags 00516 if( fcntl(dev, F_SETFL, 0) == -1 ){ 00517 serialErrno = serialErrFcntlFailed; 00518 return -1; 00519 } 00520 00521 if(tcgetattr(dev, &options) == -1 ){ 00522 serialErrno = serialErrTcGetAttrFailed; 00523 return -1; 00524 } 00525 00526 // get raw input from the port 00527 options.c_cflag |= ( CLOCAL // ignore modem control lines 00528 | CREAD ); // enable the receiver 00529 00530 options.c_iflag &= ~( IGNBRK // ignore BREAK condition on input 00531 | BRKINT // If IGNBRK is not set, generate SIGINT 00532 // on BREAK condition, else read BREAK as \0 00533 | PARMRK 00534 | ISTRIP // strip off eighth bit 00535 | INLCR // donot translate NL to CR on input 00536 | IGNCR // ignore CR 00537 | ICRNL // translate CR to newline on input 00538 | IXON // disable XON/XOFF flow control on output 00539 ); 00540 00541 // disable implementation-defined output processing 00542 options.c_oflag &= ~OPOST; 00543 options.c_lflag &= ~(ECHO // dont echo i/p chars 00544 | ECHONL // do not echo NL under any circumstance 00545 | ICANON // disable cannonical mode 00546 | ISIG // do not signal for INTR, QUIT, SUSP etc 00547 | IEXTEN // disable platform dependent i/p processing 00548 ); 00549 00550 // set a timeout on the descriptor 00551 if(itsRdTout.getVal() > 0) { 00552 options.c_cc[VMIN] = 0; 00553 options.c_cc[VTIME] = itsRdTout.getVal(); 00554 } 00555 00556 if( tcsetattr(dev, TCSANOW, &options) == -1){ 00557 serialErrno = serialErrTcSetAttrFailed; 00558 return -1; 00559 } 00560 return dev; 00561 } 00562 00563 00564 // ###################################################################### 00565 int Serial::read(void* buffer, const int nbytes) 00566 { 00567 int n = ::read(dev, buffer, nbytes); 00568 if(n==-1) 00569 serialErrno = serialErrReadFailed; 00570 00571 if(n==0) 00572 serialErrno = serialErrReadTimedOut; 00573 00574 return n; 00575 } 00576 00577 00578 // ###################################################################### 00579 char Serial::read(void) 00580 { 00581 char ch; 00582 00583 this->read(&ch, 1); 00584 00585 return ch; 00586 } 00587 00588 std::vector<unsigned char> Serial::readFrame(const unsigned char frameStart, const unsigned char frameEnd, const int frameLength, const double timeout) 00589 { 00590 00591 std::vector<unsigned char> data; 00592 unsigned char buffer[1024]; 00593 00594 Timer timer; 00595 00596 unsigned int startPos = 0; 00597 unsigned int currPos = 0; 00598 int frameSize = -1; 00599 bool done = false; 00600 int startFrameOffset = 2; 00601 00602 if(frameLength > 0) 00603 { 00604 frameSize = frameLength; 00605 startFrameOffset = 1; 00606 } 00607 00608 timer.reset(); 00609 while(!done) 00610 { 00611 //If we have reached the timeout, then just quit return an empty vector 00612 if(timeout > 0 && timer.getSecs() > timeout) 00613 return std::vector<unsigned char>(); 00614 00615 //Read data into the data buffer 00616 int bytesRead = read(buffer, 1024); 00617 00618 00619 //LINFO("Got %i bytes", bytesRead); 00620 //for(int i=0; i<bytesRead; i++) 00621 // printf("%i ", buffer[i]); 00622 //printf("\n"); 00623 00624 00625 if(bytesRead > 0) 00626 { 00627 //If we read some bytes, then let's append them onto the data buffer 00628 std::vector<unsigned char> newData(buffer, buffer+bytesRead*(sizeof(buffer[0]))); 00629 data.insert(data.end(), newData.begin(), newData.end()); 00630 00631 while(currPos < data.size()) 00632 { 00633 //If we have reached the timeout, then just quit return an empty vector 00634 if(timeout > 0 && timer.getSecs() > timeout) 00635 return std::vector<unsigned char>(); 00636 00637 if(data.at(startPos) != frameStart) 00638 { //Get the start byte position settled 00639 currPos++; 00640 startPos = currPos; 00641 } 00642 else 00643 { //Here, we already have our start byte 00644 00645 if(frameLength == -1 && frameSize == -1 && (startPos+1 < data.size()) ) 00646 { //Find the frame size if one was not supplied, and we haven't yet found it 00647 frameSize = data.at(startPos+1); 00648 currPos++; 00649 } 00650 else if(frameSize > -1 && data.size() <= currPos+frameSize+1) 00651 { //If we know our frame size, but our data buffer is not large enough, 00652 //then just break and we will read more data at the top of the while loop 00653 break; 00654 } 00655 else if(frameSize > -1 && data.size() > currPos+frameSize+1 && data.at(currPos+frameSize+1) != frameEnd) 00656 { //If we know our frame size, and have enough data, and our frame stop 00657 //byte is not there, then we need to move our startPos hypothesis one 00658 //byte forward and start the whole thing over again 00659 if(frameLength == -1) 00660 frameSize = -1; 00661 startPos++; 00662 currPos = startPos; 00663 } 00664 else if(frameSize > -1 && data.size() > currPos+frameSize+1 && data.at(currPos+frameSize+1) == frameEnd) 00665 { //All constraints satisfied - we have our frame 00666 return std::vector<unsigned char>(data.begin()+startPos+startFrameOffset, data.begin()+startPos+startFrameOffset+frameSize); 00667 } 00668 } 00669 } 00670 } 00671 else 00672 { //If the serial read returned 0 bytes, then just wait for a bit before reading again 00673 usleep(1000); 00674 00675 //If the timer has expired, then let's just return an empty vector 00676 if(timer.getSecs() > timeout && timeout > 0) 00677 return std::vector<unsigned char>(); 00678 } 00679 } 00680 return std::vector<unsigned char>(); 00681 } 00682 00683 00684 // ###################################################################### 00685 int Serial::write(const void* buffer, const int nbytes) 00686 { 00687 //char c[3] = { 0xff, 0x01, 0xff }; 00688 //::write(dev, c, 3); 00689 00690 int n = ::write(dev, buffer, nbytes); 00691 00692 /* 00693 //LINFO("----------------- WRITE --------------------"); 00694 for(int i=0; i<n; ++i) 00695 { 00696 fprintf(stderr, "%02X ", 00697 (static_cast<const unsigned char*>(buffer)[i])&0xff); 00698 } 00699 fprintf(stderr,"\n"); 00700 //LINFO("-------------------------------------------"); 00701 */ 00702 00703 if(n==-1) 00704 serialErrno = serialErrWriteFailed; 00705 00706 return n; 00707 } 00708 00709 // ###################################################################### 00710 int Serial::write(const unsigned char character) 00711 { 00712 return write(&character, 1); 00713 } 00714 00715 00716 // ###################################################################### 00717 void Serial::flush(void) 00718 { 00719 //Flush the input 00720 int status = tcflush(dev,TCIFLUSH); 00721 if(status != 0) 00722 LERROR("BAD SERIAL FLUSH"); 00723 00724 } 00725 00726 // ###################################################################### 00727 void Serial::perror(void) 00728 { 00729 switch(serialErrno) 00730 { 00731 case serialErrSuccess: 00732 LERROR("Serial::OK"); 00733 return; 00734 case serialErrOpenNoTty: 00735 LERROR("Serial::Open() No TTY Failed"); 00736 break; 00737 case serialErrOpenFailed: 00738 LERROR("Serial::Open() Failed"); 00739 break; 00740 case serialErrSpeedInvalid: 00741 LERROR("Serial::setSpeed() Invalid Speed Param"); 00742 break; 00743 case serialErrFlowInvalid: 00744 LERROR("Serial::setFlow() Invalid Flow Param"); 00745 break; 00746 case serialErrParityInvalid: 00747 LERROR("Serial::setParity() Invalid parity Param"); 00748 break; 00749 case serialErrCharsizeInvalid: 00750 LERROR("Serial::setCharSize() Invalid Char Size"); 00751 break; 00752 case serialErrStopbitsInvalid: 00753 LERROR("Serial::setStopBits() Invalid Stop Bits"); 00754 break; 00755 case serialErrOptionInvalid: 00756 LERROR("Serial::read() invalid option"); 00757 break; 00758 case serialErrOutput: 00759 LERROR("Serial::read() err output"); 00760 break; 00761 case serialErrReadFailed: 00762 LERROR("Serial::read() Failed"); 00763 break; 00764 case serialErrReadTimedOut: 00765 LERROR("Serial::read() Timed Out"); 00766 break; 00767 case serialErrWriteFailed: 00768 LERROR("Serial::Write() Failed"); 00769 break; 00770 case serialErrFcntlFailed: 00771 LERROR("Serial::Fcntl() Failed"); 00772 break; 00773 case serialErrTcGetAttrFailed: 00774 LERROR("Serial::tcgetattr() Failed"); 00775 break; 00776 case serialErrTcSetAttrFailed: 00777 LERROR("Serial::tcsetattr() Failed"); 00778 break; 00779 default: 00780 LERROR("Unknow error!"); 00781 } 00782 } 00783 00784 00785 // ###################################################################### 00786 Serial::~Serial(void) 00787 { } 00788 00789 00790 00791 // ###################################################################### 00792 /* So things look consistent in everyone's emacs... */ 00793 /* Local Variables: */ 00794 /* indent-tabs-mode: nil */ 00795 /* End: */