00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00032 #include "../../common/common.h"
00033 #include "../ymodem_tx.h"
00034
00035
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 #include <termios.h>
00040 #include <stdio.h>
00041 #include <errno.h>
00042 #include <string.h>
00043 #include <unistd.h>
00044
00048 #define DEVICE_NAME_ROOT "/dev/ttyS"
00049
00050
00051
00052
00061 class LinuxSerialPort : public SerialPort
00062 {
00063 public:
00064 LinuxSerialPort();
00065 int Open(unsigned port);
00066 int Initialise(unsigned baud);
00067 int Out(const uint8_t* data, size_t size, unsigned timeout);
00068 int In(uint8_t* data, size_t maxSize, unsigned timeout);
00069 void Close();
00070 private:
00071 ~LinuxSerialPort();
00072 int Error(int defaultError=ErrorUnspecified);
00073 private:
00074 int SerialHandle;
00075 #ifdef DEBUG_LOG
00076 void DebugDump(const char* prefix, const uint8_t* data, size_t size);
00077 FILE* DebugLog;
00078 #endif
00079 };
00080
00081
00089 int LinuxSerialPort::Error(int defaultError)
00090 {
00091 #ifdef DEBUG_LOG
00092 if(DebugLog)
00093 fprintf(DebugLog,"ERROR: %d (errno=%d '%s')",defaultError,errno,strerror(errno));
00094 #endif
00095 return defaultError;
00096 }
00097
00098
00099 int LinuxSerialPort::Open(unsigned port)
00100 {
00101
00102 char name[] = DEVICE_NAME_ROOT "???.???";
00103 char* nameNumber = name+sizeof(name)-8;
00104 char* nameEnd = nameNumber;
00105 if(port>999)
00106 return ErrorInvalidPort;
00107 if(port>99)
00108 {
00109 *nameEnd++ = '0'+port/100;
00110 port %= 100;
00111 }
00112 if(port>9)
00113 {
00114 *nameEnd++ = '0'+port/10;
00115 port %= 10;
00116 }
00117 *nameEnd++ = '0'+port;
00118 *nameEnd = 0;
00119
00120
00121 SerialHandle = open(name, O_RDWR | O_NOCTTY);
00122 if(SerialHandle<0)
00123 {
00124 switch(errno)
00125 {
00126
00127
00128
00129
00130 default:
00131 return Error(ErrorInvalidPort);
00132 }
00133 }
00134
00135 #ifdef DEBUG_LOG
00136 strcpy(nameEnd,".log");
00137 DebugLog = fopen(nameNumber,"w+b");
00138 #endif
00139
00140 return 0;
00141 }
00142
00143
00144 int LinuxSerialPort::Initialise(unsigned baud)
00145 {
00146 switch(baud)
00147 {
00148 case 1200: baud = B1200; break;
00149 case 2400: baud = B2400; break;
00150 case 4800: baud = B4800; break;
00151 case 9600: baud = B9600; break;
00152 case 19200: baud = B19200; break;
00153 case 38400: baud = B38400; break;
00154 case 57600: baud = B57600; break;
00155 case 115200: baud = B115200; break;
00156 case 230400: baud = B230400; break;
00157 default: return ErrorInvalidSettings;
00158 }
00159
00160 struct termios tio;
00161 memset(&tio, 0, sizeof(tio));
00162 tio.c_cflag = baud | CRTSCTS | CS8 | CLOCAL | CREAD;
00163 tio.c_iflag = IGNPAR;
00164 tio.c_oflag = 0;
00165 tio.c_lflag = 0;
00166 tio.c_cc[VTIME] = 0;
00167 tio.c_cc[VMIN] = 0;
00168
00169 tcflush(SerialHandle, TCIFLUSH);
00170 if(tcsetattr(SerialHandle,TCSANOW,&tio)<0)
00171 return ErrorInvalidSettings;
00172
00173 return 0;
00174 }
00175
00176
00177 int LinuxSerialPort::Out(const uint8_t* data, size_t size, unsigned timeout)
00178 {
00179 retry:
00180
00181 fd_set writefds;
00182 FD_ZERO(&writefds);
00183 FD_SET(SerialHandle,&writefds);
00184 timeval wait;
00185 wait.tv_sec = timeout/1000;
00186 wait.tv_usec = timeout%1000*1000;
00187 int selectResult = select(SerialHandle+1, 0, &writefds, 0, &wait);
00188
00189 int bytes;
00190 if(selectResult==0)
00191 {
00192
00193 bytes = 0;
00194 }
00195 else if(selectResult<0)
00196 {
00197
00198 if(errno==EINTR)
00199 goto retry;
00200 bytes = -1;
00201 }
00202 else
00203 {
00204
00205 bytes = write(SerialHandle,data,size);
00206 }
00207
00208 if(bytes<0)
00209 return Error(ErrorTransmitError);
00210
00211 #ifdef DEBUG_LOG
00212 DebugDump(">",data,bytes);
00213 #endif
00214
00215 return bytes;
00216 }
00217
00218
00219 int LinuxSerialPort::In(uint8_t* data, size_t maxSize, unsigned timeout)
00220 {
00221 retry:
00222
00223 fd_set readfds;
00224 FD_ZERO(&readfds);
00225 FD_SET(SerialHandle,&readfds);
00226 timeval wait;
00227 wait.tv_sec = timeout/1000;
00228 wait.tv_usec = timeout%1000*1000;
00229 int selectResult = select(SerialHandle+1, &readfds, 0, 0, &wait);
00230
00231 int bytes;
00232 if(selectResult==0)
00233 {
00234
00235 bytes = 0;
00236 }
00237 else if(selectResult<0)
00238 {
00239
00240 if(errno==EINTR)
00241 goto retry;
00242 bytes = -1;
00243 }
00244 else
00245 {
00246
00247 bytes = read(SerialHandle,data,maxSize);
00248 }
00249
00250 if(bytes<0)
00251 return Error(ErrorReceiveError);
00252
00253 #ifdef DEBUG_LOG
00254 DebugDump("<",data,bytes);
00255 #endif
00256
00257 return bytes;
00258 }
00259
00260
00261 void LinuxSerialPort::Close()
00262 {
00263 if(SerialHandle)
00264 {
00265 close(SerialHandle);
00266 SerialHandle = 0;
00267 }
00268 #ifdef DEBUG_LOG
00269 if(DebugLog)
00270 {
00271 fclose(DebugLog);
00272 DebugLog = 0;
00273 }
00274 #endif
00275 }
00276
00277
00278 #ifdef DEBUG_LOG
00279
00280 void LinuxSerialPort::DebugDump(const char* prefix, const uint8_t* data, size_t size)
00281 {
00282 if(!DebugLog)
00283 return;
00284
00285 size_t i=0;
00286 while(i<size)
00287 {
00288 fprintf(DebugLog,prefix);
00289 unsigned j;
00290 for(j=0; j<16 && i+j<size; j++)
00291 {
00292 fprintf(DebugLog," %02x",data[i+j]);
00293 }
00294 fprintf(DebugLog," ");
00295 for(unsigned k=0; k<j; k++)
00296 {
00297 uint8_t c = data[i+k];
00298 if(c<' '|| c>=0x7f)
00299 c = '.';
00300 fprintf(DebugLog,"%c",c);
00301 }
00302 fprintf(DebugLog,"\n");
00303 i += j;
00304 }
00305 }
00306
00307 #endif
00308
00309
00310 inline LinuxSerialPort::LinuxSerialPort()
00311 : SerialHandle(0)
00312 #ifdef DEBUG_LOG
00313 ,DebugLog(0)
00314 #endif
00315 {
00316 }
00317
00318
00319 LinuxSerialPort::~LinuxSerialPort()
00320 {
00321 Close();
00322 }
00323
00324
00325 SerialPort* SerialPort::New()
00326 {
00327 return new LinuxSerialPort;
00328 }
00329
00330
00331 SerialPort::~SerialPort()
00332 {
00333 }
00334
00335