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 "windows.h"
00037
00038
00039
00040
00041
00042 #ifdef DEBUG_LOG
00043 #include "stdio.h"
00044 #endif
00045
00046
00051 class WindowsSerialPort : public SerialPort
00052 {
00053 public:
00054 WindowsSerialPort();
00055 int Open(unsigned port);
00056 int Initialise(unsigned baud);
00057 int Out(const uint8_t* data, size_t size, unsigned timeout);
00058 int In(uint8_t* data, size_t maxSize, unsigned timeout);
00059 void Close();
00060 private:
00061 ~WindowsSerialPort();
00062 int Error(int defaultError=ErrorUnspecified);
00063 private:
00064 HANDLE hSerial;
00065 #ifdef DEBUG_LOG
00066 void DebugDump(const char* prefix, const uint8_t* data, size_t size);
00067 FILE* DebugLog;
00068 #endif
00069 };
00070
00071
00079 int WindowsSerialPort::Error(int defaultError)
00080 {
00081 #ifdef DEBUG_LOG
00082 char errorMessage[1024];
00083 DWORD error = GetLastError();
00084 FormatMessage
00085 (
00086 FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
00087 NULL,
00088 error,
00089 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00090 errorMessage,
00091 sizeof(errorMessage),
00092 NULL
00093 );
00094 OutputDebugString(errorMessage);
00095 if(DebugLog)
00096 fprintf(DebugLog,"ERROR: Windows error %d : %s",error,errorMessage);
00097 BREAKPOINT;
00098
00099 #endif
00100
00101
00102 return defaultError;
00103 }
00104
00105
00106 int WindowsSerialPort::Open(unsigned port)
00107 {
00108
00109 char name[] = "\\\\.\\com???.???";
00110 char* nameNumber = name+sizeof(name)-8;
00111 char* nameEnd = nameNumber;
00112 if(port>999)
00113 return ErrorInvalidPort;
00114 if(port>99)
00115 {
00116 *nameEnd++ = '0'+port/100;
00117 port %= 100;
00118 }
00119 if(port>9)
00120 {
00121 *nameEnd++ = '0'+port/10;
00122 port %= 10;
00123 }
00124 *nameEnd++ = '0'+port;
00125 *nameEnd = 0;
00126
00127
00128 hSerial = CreateFile(name, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
00129 if(hSerial==INVALID_HANDLE_VALUE)
00130 {
00131 switch(GetLastError())
00132 {
00133 case ERROR_FILE_NOT_FOUND:
00134 return ErrorInvalidPort;
00135 case ERROR_ACCESS_DENIED:
00136 return ErrorPortInUse;
00137 default:
00138 return Error();
00139 }
00140 }
00141
00142 #ifdef DEBUG_LOG
00143 strcpy(nameEnd,".log");
00144 DebugLog = fopen(nameNumber,"w+b");
00145 #endif
00146
00147 return 0;
00148 }
00149
00150
00151 int WindowsSerialPort::Initialise(unsigned baud)
00152 {
00153
00154 if(!FlushFileBuffers(hSerial))
00155 return Error();
00156 if(!PurgeComm(hSerial, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR))
00157 return Error();
00158
00159
00160 DCB dcb = {0};
00161 if(!GetCommState(hSerial, &dcb))
00162 return Error();
00163 dcb.BaudRate = baud;
00164 dcb.ByteSize = 8;
00165 dcb.StopBits = ONESTOPBIT;
00166 dcb.Parity = NOPARITY;
00167 if(!SetCommState(hSerial, &dcb))
00168 {
00169 if(GetLastError()==ERROR_INVALID_PARAMETER)
00170 return ErrorInvalidSettings;
00171 return Error();
00172 }
00173
00174
00175 COMMTIMEOUTS timeouts = {0};
00176 timeouts.ReadIntervalTimeout = MAXDWORD;
00177 timeouts.ReadTotalTimeoutConstant = 0;
00178 timeouts.ReadTotalTimeoutMultiplier = 0;
00179 timeouts.WriteTotalTimeoutConstant = 0;
00180 timeouts.WriteTotalTimeoutMultiplier= 0;
00181 if(!SetCommTimeouts(hSerial, &timeouts))
00182 return Error();
00183
00184
00185 if(!PurgeComm(hSerial, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR))
00186 return Error();
00187
00188 return 0;
00189 }
00190
00191
00192 int WindowsSerialPort::Out(const uint8_t* data, size_t size, unsigned timeout)
00193 {
00194 DWORD bytes = 0;
00195 for(;;)
00196 {
00197
00198 if(!WriteFile(hSerial,data,size,&bytes,NULL))
00199 return Error(ErrorTransmitError);
00200 if(bytes)
00201 break;
00202 if(timeout==0)
00203 break;
00204
00205
00206 unsigned sleep = 10;
00207 if(sleep>timeout)
00208 sleep = timeout;
00209 timeout -= sleep;
00210 Sleep(sleep);
00211 }
00212
00213 #ifdef DEBUG_LOG
00214 DebugDump(">",data,bytes);
00215 #endif
00216
00217 return bytes;
00218 }
00219
00220
00221 int WindowsSerialPort::In(uint8_t* data, size_t maxSize, unsigned timeout)
00222 {
00223 DWORD bytes = 0;
00224 for(;;)
00225 {
00226
00227 if(!ReadFile(hSerial,data,maxSize,&bytes,NULL))
00228 return Error(ErrorReceiveError);
00229 if(bytes)
00230 break;
00231 if(timeout==0)
00232 break;
00233
00234
00235 unsigned sleep = 10;
00236 if(sleep>timeout)
00237 sleep = timeout;
00238 timeout -= sleep;
00239 Sleep(sleep);
00240 }
00241
00242 #ifdef DEBUG_LOG
00243 DebugDump("<",data,bytes);
00244 #endif
00245
00246 return bytes;
00247 }
00248
00249
00250 #ifdef DEBUG_LOG
00251
00252 void WindowsSerialPort::DebugDump(const char* prefix, const uint8_t* data, size_t size)
00253 {
00254 if(!DebugLog)
00255 return;
00256
00257 size_t i=0;
00258 while(i<size)
00259 {
00260 fprintf(DebugLog,prefix);
00261 unsigned j;
00262 for(j=0; j<16 && i+j<size; j++)
00263 {
00264 fprintf(DebugLog," %02x",data[i+j]);
00265 }
00266 fprintf(DebugLog," ");
00267 for(unsigned k=0; k<j; k++)
00268 {
00269 uint8_t c = data[i+k];
00270 if(c<' '|| c>=0x7f)
00271 c = '.';
00272 fprintf(DebugLog,"%c",c);
00273 }
00274 fprintf(DebugLog,"\n");
00275 i += j;
00276 }
00277 }
00278
00279 #endif
00280
00281
00282 void WindowsSerialPort::Close()
00283 {
00284 if(hSerial!=INVALID_HANDLE_VALUE)
00285 {
00286 CloseHandle(hSerial);
00287 hSerial = INVALID_HANDLE_VALUE;
00288 }
00289 #ifdef DEBUG_LOG
00290 if(DebugLog)
00291 {
00292 fclose(DebugLog);
00293 DebugLog = 0;
00294 }
00295 #endif
00296 }
00297
00298
00299 inline WindowsSerialPort::WindowsSerialPort()
00300 : hSerial(0)
00301 #ifdef DEBUG_LOG
00302 ,DebugLog(0)
00303 #endif
00304 {
00305 }
00306
00307
00308 WindowsSerialPort::~WindowsSerialPort()
00309 {
00310 Close();
00311 }
00312
00313
00314 SerialPort* SerialPort::New()
00315 {
00316 return new WindowsSerialPort;
00317 }
00318
00319
00320 SerialPort::~SerialPort()
00321 {
00322 }
00323
00324