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

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

Parent Directory Parent Directory | Revision Log Revision Log


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


1 #ifndef _MSC_VER //linux
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5 #include <errno.h>
6 #include <termios.h>
7 #include <fcntl.h>
8 #endif
9
10 #include "Serial.h"
11
12 #include <stdexcept>
13 #include <string>
14 #include <sstream>
15
16
17 #ifdef DEBUG
18 #include <iostream>
19 #include <iomanip>
20 #endif
21
22
23
24
25 std::string writeLastError()
26 {
27 #ifdef _MSC_VER
28 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 out << "Error " << lpMsgBuf;
39 return out.str();
40 #else //linux
41 return std::string( strerror(errno) );
42 #endif
43 }
44
45
46 CSerial::CSerial()
47 {
48 mIsopen = false;
49 }
50
51
52 CSerial::CSerial(char* port, Baudrate bitrate)
53 {
54 mPortstr = port;
55 mBitrate = bitrate;
56 mIsopen = false;
57
58 #ifdef _MSC_VER
59 openWindows();
60 #else
61 openLinux();
62 #endif
63 }
64
65 CSerial::~CSerial(void)
66 {
67 close();
68 }
69
70 void CSerial::open(char* port, Baudrate bitrate)
71 {
72 if (mIsopen)
73 throw std::runtime_error("Port already opened");
74
75 mPortstr = port;
76 mBitrate = bitrate;
77
78 #ifdef _MSC_VER
79 openWindows();
80 #else
81 openLinux();
82 #endif
83 }
84
85 #ifdef _MSC_VER
86 void CSerial::openWindows()
87 {
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 throw std::runtime_error(writeLastError().c_str());
93 }
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 dcb.BaudRate = convertBaudrate(mBitrate);
107 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 throw std::runtime_error( error );
120 }
121
122 mIsopen = true;
123 }
124 #endif
125
126
127 #ifndef _MSC_VER
128 void CSerial::openLinux()
129 {
130 termios newtio;
131
132 mFiledescriptor = ::open(mPortstr, O_RDWR | O_NOCTTY | O_NONBLOCK);
133 if (mFiledescriptor < 0)
134 throw std::runtime_error( writeLastError() );
135
136 tcgetattr(mFiledescriptor, &mOldtio);
137
138 bzero(&newtio, sizeof(newtio) );
139
140 // use a std. 8N1 config
141 newtio.c_cflag = convertBaudrate(mBitrate) | CS8 | CLOCAL | CREAD;
142 newtio.c_iflag = IGNPAR;
143 newtio.c_oflag = 0;
144
145 // set input mode (non-canonical, no echo,...)
146 newtio.c_lflag = 0;
147
148 newtio.c_cc[VTIME] = 0; // inter-character timer unused
149 newtio.c_cc[VMIN] = 0; // blocking read until 1 chars received
150
151
152 tcflush(mFiledescriptor, TCIFLUSH);
153 tcsetattr(mFiledescriptor, TCSANOW, &newtio);
154
155 mIsopen = true;
156 }
157 #endif
158
159 void CSerial::close()
160 {
161 if (mIsopen)
162 {
163 #ifdef _MSC_VER
164 while (getComstat().cbOutQue >0)
165 Sleep(5);
166 SetCommState(mComport,&mDcbRestore);
167 CloseHandle(mComport);
168 #else // linux close()
169 tcdrain(mFiledescriptor);
170 tcsetattr(mFiledescriptor, TCSADRAIN, &mOldtio); //restore settings, when all data is written
171 ::close(mFiledescriptor); //close()== system-call
172 #endif
173 mIsopen = false;
174 }
175 }
176
177
178 int CSerial::readByte()
179 {
180 unsigned char out;
181 int size = readBytes(&out,1);
182
183 if (size == 0)
184 return 256;
185
186 return out;
187 }
188
189
190 void CSerial::writeByte(unsigned char out)
191 {
192 writeBytes(&out,1);
193 }
194
195 int CSerial::convertBaudrate(Baudrate rate)
196 {
197 int retval=0;
198 #ifdef _MSC_VER
199 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 case Baud115200:
229 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 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 #endif
283
284 int CSerial::bytesReady() const
285 {
286 #ifdef _MSC_VER
287 return getComstat().cbInQue;
288 #else
289 return 0;
290 #endif
291 }
292
293 int CSerial::outQueueSize() const
294 {
295 #ifdef _MSC_VER
296 return getComstat().cbOutQue;
297 #else
298 return 0;
299 #endif
300 }
301
302 // Debug function
303 //
304 void CSerial::printByte(char* description, unsigned char byte)
305 {
306 #ifdef DEBUG
307 std::cout << description << " : " << (int) byte << "/" << std::setw(2) << std::setfill('0') << std::hex << (int) byte << std::endl;
308 std::cout << std::dec;
309 #endif
310 }
311
312
313
314 void CSerial::writeBytes(unsigned char* buf, unsigned int len)
315 {
316 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
325
326 #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 {
336 std::string error = writeLastError();
337 CloseHandle(mComport);
338 throw std::exception(error.c_str());
339 }
340 }
341
342 #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
353 int CSerial::readBytes(unsigned char *buf, unsigned int maxLen)
354 {
355 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
364
365 #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
373 #else
374
375 int CSerial::readBytesLinux(unsigned char* buf, unsigned int maxLen)
376 {
377 return read(mFiledescriptor, buf, maxLen);
378 }
379
380 #endif

  ViewVC Help
Powered by ViewVC 1.1.20