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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 56 - (show annotations) (download)
Mon Feb 5 10:24:24 2007 UTC (17 years, 3 months ago) by torben
File size: 7236 byte(s)
Cleanup ....


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

  ViewVC Help
Powered by ViewVC 1.1.20