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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (hide annotations) (download)
Mon Feb 5 10:10:18 2007 UTC (17 years, 3 months ago) by torben
File size: 7579 byte(s)
Added a cross-platform specification of desired baud-rate.

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

  ViewVC Help
Powered by ViewVC 1.1.20