/[H7]/branches/linux-serial/Serial.cpp
ViewVC logotype

Annotation of /branches/linux-serial/Serial.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 76 - (hide annotations) (download)
Wed Jun 4 13:06:09 2008 UTC (16 years ago) by torben
File size: 7019 byte(s)
Cleaned up the code a bit


1 torben 49 #ifndef _MSC_VER //linux
2 torben 46 #include <sys/types.h>
3     #include <sys/stat.h>
4     #include <unistd.h>
5 torben 44 #include <errno.h>
6 torben 46 #include <termios.h>
7     #include <fcntl.h>
8 torben 44 #endif
9 torben 38
10 torben 58 #include "Serial.h"
11 torben 38
12 torben 44 #include <stdexcept>
13 torben 38 #include <string>
14     #include <sstream>
15 torben 56
16 torben 58
17 torben 56 #ifdef DEBUG
18 torben 46 #include <iostream>
19 torben 38 #include <iomanip>
20 torben 56 #endif
21 torben 38
22 torben 46
23    
24 torben 58
25 torben 38 std::string writeLastError()
26     {
27 torben 49 #ifdef _MSC_VER
28 torben 38 LPVOID lpMsgBuf;
29     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
30     NULL,
31     GetLastError(),
32     MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
33     (LPSTR) &lpMsgBuf,
34     0,
35     NULL);
36    
37     std::ostringstream out;
38 torben 57 out << "Error " << lpMsgBuf;
39 torben 38 return out.str();
40 torben 44 #else //linux
41 torben 46 return std::string( strerror(errno) );
42 torben 44 #endif
43 torben 38 }
44    
45    
46     CSerial::CSerial()
47     {
48     mIsopen = false;
49     }
50    
51 torben 54
52     CSerial::CSerial(char* port, Baudrate bitrate)
53 torben 38 {
54     mPortstr = port;
55     mBitrate = bitrate;
56     mIsopen = false;
57    
58 torben 49 #ifdef _MSC_VER
59 torben 44 openWindows();
60     #else
61     openLinux();
62     #endif
63 torben 38 }
64    
65     CSerial::~CSerial(void)
66     {
67     close();
68     }
69    
70 torben 54 void CSerial::open(char* port, Baudrate bitrate)
71 torben 38 {
72     if (mIsopen)
73 torben 44 throw std::runtime_error("Port already opened");
74 torben 38
75     mPortstr = port;
76     mBitrate = bitrate;
77 torben 44
78 torben 49 #ifdef _MSC_VER
79 torben 44 openWindows();
80     #else
81     openLinux();
82     #endif
83 torben 38 }
84    
85 torben 49 #ifdef _MSC_VER
86 torben 44 void CSerial::openWindows()
87 torben 38 {
88     mComport = CreateFile( mPortstr, GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
89    
90     if (mComport == INVALID_HANDLE_VALUE)
91     {
92 torben 44 throw std::runtime_error(writeLastError().c_str());
93 torben 38 }
94    
95     DCB dcb;
96     dcb.DCBlength = sizeof(DCB);
97     mDcbRestore.DCBlength = sizeof(DCB);
98    
99     if (!GetCommState(mComport,&dcb) || !GetCommState(mComport,&mDcbRestore))
100     {
101     std::string error = writeLastError();
102     CloseHandle(mComport);
103     throw std::exception(error.c_str());
104     }
105    
106 torben 54 dcb.BaudRate = convertBaudrate(mBitrate);
107 torben 38 dcb.ByteSize = 8;
108     dcb.Parity = NOPARITY;
109     dcb.StopBits = ONESTOPBIT;
110     dcb.fDtrControl = DTR_CONTROL_DISABLE;
111     dcb.fRtsControl = RTS_CONTROL_DISABLE;
112     dcb.fParity = false;
113     dcb.fDsrSensitivity = false;
114    
115     if (!SetCommState(mComport,&dcb))
116     {
117     std::string error = writeLastError();
118     CloseHandle(mComport);
119 torben 49 throw std::runtime_error( error );
120 torben 38 }
121    
122     mIsopen = true;
123     }
124 torben 44 #endif
125 torben 38
126 torben 44
127 torben 49 #ifndef _MSC_VER
128 torben 44 void CSerial::openLinux()
129     {
130 torben 46 termios newtio;
131    
132 torben 57 mFiledescriptor = ::open(mPortstr, O_RDWR | O_NOCTTY | O_NONBLOCK);
133 torben 46 if (mFiledescriptor < 0)
134     throw std::runtime_error( writeLastError() );
135    
136 torben 73 tcgetattr(mFiledescriptor, &mOldtio);
137    
138 torben 46 bzero(&newtio, sizeof(newtio) );
139    
140     // use a std. 8N1 config
141 torben 61 newtio.c_cflag = convertBaudrate(mBitrate) | CS8 | CLOCAL | CREAD;
142 torben 46 newtio.c_iflag = IGNPAR;
143     newtio.c_oflag = 0;
144    
145 torben 54 // set input mode (non-canonical, no echo,...)
146 torben 46 newtio.c_lflag = 0;
147    
148 torben 54 newtio.c_cc[VTIME] = 0; // inter-character timer unused
149     newtio.c_cc[VMIN] = 0; // blocking read until 1 chars received
150    
151 torben 46
152     tcflush(mFiledescriptor, TCIFLUSH);
153     tcsetattr(mFiledescriptor, TCSANOW, &newtio);
154    
155     mIsopen = true;
156 torben 44 }
157     #endif
158    
159 torben 38 void CSerial::close()
160     {
161     if (mIsopen)
162     {
163 torben 49 #ifdef _MSC_VER
164 torben 38 while (getComstat().cbOutQue >0)
165     Sleep(5);
166     SetCommState(mComport,&mDcbRestore);
167     CloseHandle(mComport);
168 torben 44 #else // linux close()
169 torben 46 tcdrain(mFiledescriptor);
170     tcsetattr(mFiledescriptor, TCSADRAIN, &mOldtio); //restore settings, when all data is written
171     ::close(mFiledescriptor); //close()== system-call
172 torben 44 #endif
173 torben 38 mIsopen = false;
174     }
175     }
176    
177    
178 torben 47 int CSerial::readByte()
179 torben 38 {
180     unsigned char out;
181 torben 76 int size = readBytes(&out,1);
182 torben 38
183 torben 76 if (size == 0)
184     return 256;
185 torben 38
186     return out;
187     }
188    
189    
190     void CSerial::writeByte(unsigned char out)
191     {
192 torben 76 writeBytes(&out,1);
193 torben 38 }
194 torben 46
195 torben 54 int CSerial::convertBaudrate(Baudrate rate)
196     {
197     int retval=0;
198 torben 49 #ifdef _MSC_VER
199 torben 54 switch( rate )
200     {
201     case Baud300:
202     retval = 300;
203     break;
204     case Baud600:
205     retval = 600;
206     break;
207     case Baud1200:
208     retval = 1200;
209     break;
210     case Baud2400:
211     retval = 2400;
212     break;
213     case Baud4800:
214     retval = 4800;
215     break;
216     case Baud9600:
217     retval = 9600;
218     break;
219     case Baud19200:
220     retval = 19200;
221     break;
222     case Baud38400:
223     retval = 38400;
224     break;
225     case Baud57600:
226     retval = 57600;
227     break;
228 torben 55 case Baud115200:
229 torben 54 retval = 115200;
230     break;
231     }
232     #else
233     switch (rate)
234     {
235     case Baud300:
236     retval = B300;
237     break;
238     case Baud600:
239     retval = B600;
240     break;
241     case Baud1200:
242     retval = B1200;
243     break;
244     case Baud2400:
245     retval = B2400;
246     break;
247     case Baud4800:
248     retval = B4800;
249     break;
250     case Baud9600:
251     retval = B9600;
252     break;
253     case Baud19200:
254     retval = B19200;
255     break;
256     case Baud38400:
257     retval = B38400;
258     break;
259     case Baud57600:
260     retval = B57600;
261     break;
262     case Baud115200:
263     retval = B115200;
264     break;
265     }
266     #endif
267    
268     return retval;
269     }
270    
271     #ifdef _MSC_VER
272 torben 38 COMSTAT CSerial::getComstat() const
273     {
274     if (!mIsopen)
275     throw std::exception("Port not opened");
276    
277     COMSTAT stat;
278     DWORD x;
279     ClearCommError(mComport,&x,&stat);
280     return stat;
281     }
282 torben 44 #endif
283 torben 38
284     int CSerial::bytesReady() const
285     {
286 torben 49 #ifdef _MSC_VER
287 torben 38 return getComstat().cbInQue;
288 torben 44 #else
289     return 0;
290     #endif
291 torben 38 }
292    
293     int CSerial::outQueueSize() const
294     {
295 torben 49 #ifdef _MSC_VER
296 torben 38 return getComstat().cbOutQue;
297 torben 44 #else
298     return 0;
299     #endif
300 torben 38 }
301    
302 torben 46 // Debug function
303     //
304 torben 38 void CSerial::printByte(char* description, unsigned char byte)
305     {
306 torben 56 #ifdef DEBUG
307 torben 38 std::cout << description << " : " << (int) byte << "/" << std::setw(2) << std::setfill('0') << std::hex << (int) byte << std::endl;
308     std::cout << std::dec;
309 torben 56 #endif
310 torben 38 }
311    
312 torben 46
313 torben 76
314     void CSerial::writeBytes(unsigned char* buf, unsigned int len)
315 torben 38 {
316 torben 76 if (!mIsopen)
317     throw std::runtime_error("Port not opened");
318     #ifdef _MSC_VER
319     writeBytesWindows(buf,len);
320     #else
321     writeBytesLinux(buf,len);
322     #endif
323     }
324 torben 38
325    
326 torben 76 #ifdef _MSC_VER
327     void CSerial::writeBytesWindows(unsigned char* buf, unsigned int len)
328     {
329     unsigned int size;
330     while (getComstat().cbOutQue >0)
331     Sleep(2);
332    
333     WriteFile(mComport,buf,len,&size, NULL);
334     if (size != len)
335 torben 38 {
336     std::string error = writeLastError();
337     CloseHandle(mComport);
338     throw std::exception(error.c_str());
339     }
340     }
341    
342 torben 76 #else
343     void CSerial::writeBytesLinux(unsigned char* buf, unsigned int len)
344     {
345     int size = write(mFiledescriptor, &buf, len);
346     Sleep(50);
347     //tcdrain(mFiledescriptor);
348     if (size != len)
349     throw std::runtime_error(writeLastError() );
350     }
351     #endif
352 torben 38
353 torben 76 int CSerial::readBytes(unsigned char *buf, unsigned int maxLen)
354 torben 38 {
355 torben 76 if (!mIsopen)
356     throw std::runtime_error("Port not opened");
357     #ifdef _MSC_VER
358     return readBytesWindows(buf,maxLen);
359     #else
360     return readBytesLinux(buf,maxLen);
361     #endif
362     }
363 torben 38
364    
365 torben 76 #ifdef _MSC_VER
366     int CSerial::readBytesWindows(unsigned char* buf, unsigned int maxLen)
367     {
368     unsigned long size;
369     ReadFile(mComport, buf, maxLen, &size, 0);
370     return size;
371     }
372 torben 38
373 torben 76 #else
374    
375     int CSerial::readBytesLinux(unsigned char* buf, unsigned int maxLen)
376     {
377     return read(mFiledescriptor, buf, maxLen);
378 torben 38 }
379 torben 76
380     #endif

  ViewVC Help
Powered by ViewVC 1.1.20