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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 73 - (show annotations) (download)
Fri Jul 6 11:31:48 2007 UTC (16 years, 10 months ago) by torben
File size: 7073 byte(s)
Make sure the old port settings is saven in linuxOpen()


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

  ViewVC Help
Powered by ViewVC 1.1.20