comparison host/tools/ecostest/common/eCosTestSerial.cpp @ 76:435cced73e2f ecos-v1_3_1-release

eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
author jlarmour
date Tue, 28 Mar 2000 14:10:45 +0000
parents
children
comparison
equal deleted inserted replaced
75:41bf073c0c32 76:435cced73e2f
1 //####COPYRIGHTBEGIN####
2 //
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
11 // any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 // more details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //
24 //####COPYRIGHTEND####
25 //=================================================================
26 //
27 // eCosTestSerial.cpp
28 //
29 // Serial test class
30 //
31 //=================================================================
32 //=================================================================
33 //#####DESCRIPTIONBEGIN####
34 //
35 // Author(s): sdf
36 // Contributors: sdf
37 // Date: 1999-04-01
38 // Description: This class abstracts the serial port for use in the testing infrastructure
39 // Usage:
40 //
41 //####DESCRIPTIONEND####
42
43 #include "eCosStd.h"
44 #include "eCosTestSerial.h"
45 #include "eCosTrace.h"
46
47 CeCosTestSerial::CeCosTestSerial():
48 m_nErr(0),
49 m_pHandle(0),
50 m_nDataBits(8),
51 m_nStopBits(ONE_STOP_BIT),
52 m_bParity(false),
53 m_nBaud(0),
54 m_nTotalReadTimeout(10*1000),
55 m_nTotalWriteTimeout(10*1000),
56 m_nInterCharReadTimeout(500),
57 m_nInterCharWriteTimeout(500),
58 m_bBlockingReads(true)
59 {
60 }
61
62 CeCosTestSerial::~CeCosTestSerial()
63 {
64 Close();
65 }
66
67 CeCosTestSerial::CeCosTestSerial(LPCTSTR pszPort,int nBaud):
68 m_nErr(0),
69 m_pHandle(0),
70 m_nDataBits(8),
71 m_nStopBits(ONE_STOP_BIT),
72 m_bParity(false),
73 m_nTotalReadTimeout(10*1000),
74 m_nTotalWriteTimeout(10*1000),
75 m_nInterCharReadTimeout(500),
76 m_nInterCharWriteTimeout(500),
77 m_bBlockingReads(true)
78 {
79 Open(pszPort,nBaud);
80 }
81
82 bool CeCosTestSerial::SetBlockingReads(bool b,bool bApplySettingsNow/*=true*/)
83 {
84 m_bBlockingReads=b;
85 return 0==m_pHandle || !bApplySettingsNow || ApplySettings();
86 }
87
88 bool CeCosTestSerial:: SetBaud(unsigned int nBaud,bool bApplySettingsNow/*=true*/)
89 {
90 m_nBaud=nBaud;
91 return 0==m_pHandle || !bApplySettingsNow || ApplySettings();
92 }
93
94 bool CeCosTestSerial:: SetParity(bool bParityOn,bool bApplySettingsNow/*=true*/)
95 {
96 m_bParity=bParityOn;
97 return 0==m_pHandle || !bApplySettingsNow || ApplySettings();
98 }
99
100 bool CeCosTestSerial:: SetDataBits(int n,bool bApplySettingsNow/*=true*/)
101 {
102 m_nDataBits=n;
103 return 0==m_pHandle || !bApplySettingsNow || ApplySettings();
104 }
105
106 bool CeCosTestSerial:: SetStopBits(StopBitsType n,bool bApplySettingsNow/*=true*/)
107 {
108 m_nStopBits=n;
109 return 0==m_pHandle || !bApplySettingsNow || ApplySettings();
110 }
111
112 bool CeCosTestSerial:: SetReadTimeOuts(int nTotal,int nBetweenChars,bool bApplySettingsNow/*=true*/) // mSec
113 {
114 m_nTotalReadTimeout=nTotal;
115 m_nInterCharReadTimeout=nBetweenChars;
116
117 return 0==m_pHandle || !bApplySettingsNow || ApplySettings();
118 }
119
120 bool CeCosTestSerial:: SetWriteTimeOuts(int nTotal,int nBetweenChars,bool bApplySettingsNow/*=true*/) // mSec
121 {
122 m_nTotalWriteTimeout=nTotal;
123 m_nInterCharWriteTimeout=nBetweenChars;
124 return 0==m_pHandle || !bApplySettingsNow || ApplySettings();
125 }
126 /*
127 bool CeCosTestSerial::Read (String &str)
128 {
129 TCHAR *c=str.GetBuffer();
130 unsigned int nRead=0;
131 bool rc=Read(c,str.GetLength(),nRead);
132 c[nRead]=_TCHAR('\0');
133 str.ReleaseBuffer();
134 return rc;
135 }
136
137 bool CeCosTestSerial::Write(const String &str)
138 {
139 unsigned int nWritten=0;
140 return Write((void *)(LPCTSTR)str,str.GetLength(),nWritten) && nWritten==str.GetLength();
141 }
142 */
143 #ifdef _WIN32
144 bool CeCosTestSerial::Open(LPCTSTR pszPort,int nBaud)
145 {
146 bool rc=false;
147 m_nBaud=nBaud,
148 m_strPort=pszPort;
149 HANDLE hCom=::CreateFile(pszPort,GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,0,NULL);
150 SaveError();
151 if (INVALID_HANDLE_VALUE==hCom) {
152 ERROR(_T("Failed to open port %s - %s\n"),pszPort,(LPCTSTR)ErrString());
153 } else {
154 m_pHandle=(void *)hCom;
155 if(ApplySettings()){
156 Flush();
157 rc=true;
158 } else {
159 Close();
160 }
161 }
162 return rc;
163 }
164
165 bool CeCosTestSerial::Close()
166 {
167 bool rc=false;
168 if(m_pHandle){
169 try {
170 rc=(TRUE==CloseHandle((HANDLE)m_pHandle));
171 }
172 catch(...) {
173 TRACE(_T("!!! Exception caught closing serial handle %08x\n"),m_pHandle);
174 }
175 m_pHandle=0;
176 } else {
177 rc=true;
178 }
179 return rc;
180 }
181
182 bool CeCosTestSerial::ApplySettings()
183 {
184 bool rc=false;
185 try {
186 DCB dcb;
187
188 ZeroMemory(&dcb,sizeof dcb);
189 dcb.DCBlength=sizeof dcb;
190 dcb.BaudRate=m_nBaud;
191 dcb.fBinary=true;
192 dcb.fParity=true;
193 dcb.Parity=(BYTE) ((m_bParity) ? EVENPARITY : NOPARITY);
194 dcb.StopBits=(BYTE)m_nStopBits;
195 dcb.ByteSize=(BYTE)m_nDataBits;
196 LPCTSTR arpszStopbits[3]={_T("1"),_T("1.5"),_T("2")};
197 TRACE(_T("Applysettings baud=%d Parity=%d stopbits=%s databits=%d\n"),
198 dcb.BaudRate,
199 dcb.Parity,
200 arpszStopbits[dcb.StopBits],
201 dcb.ByteSize);
202
203 // No control over the following yet
204 dcb.fDtrControl=DTR_CONTROL_ENABLE;
205 dcb.fTXContinueOnXoff=1;
206 dcb.fRtsControl=RTS_CONTROL_ENABLE;
207 dcb.fAbortOnError=1;
208 dcb.XonLim=2048;
209 dcb.XoffLim=512;
210 dcb.XonChar=17;
211 dcb.XoffChar=19;
212
213 HANDLE hCom=(HANDLE)m_pHandle;
214 if (!SetCommState(hCom, &dcb)) {
215 SaveError();
216 ERROR(_T("Failed to set comm state - port %s handle=%d err=%d\n"),(LPCTSTR)m_strPort,hCom,GetLastError());
217 } else {
218 COMMTIMEOUTS commtimeouts;
219 if(m_bBlockingReads){
220 commtimeouts.ReadIntervalTimeout=m_nInterCharReadTimeout;
221 commtimeouts.ReadTotalTimeoutMultiplier=0;
222 commtimeouts.ReadTotalTimeoutConstant=m_nTotalReadTimeout;
223 } else {
224 commtimeouts.ReadIntervalTimeout=MAXDWORD;
225 commtimeouts.ReadTotalTimeoutMultiplier=0;
226 commtimeouts.ReadTotalTimeoutConstant=0;
227 }
228 commtimeouts.WriteTotalTimeoutMultiplier=m_nTotalWriteTimeout;
229 commtimeouts.WriteTotalTimeoutConstant=m_nInterCharWriteTimeout;
230
231 if (SetCommTimeouts(hCom, &commtimeouts)) {
232 rc=true;
233 } else {
234 SaveError();
235 ERROR(_T("Failed to set comm timeouts - port %s\n"),(LPCTSTR)m_strPort);
236 }
237 }
238 }
239 catch(...)
240 {
241 TRACE(_T("!!! Exception caught in CeCosTestSerial::ApplySettings!!!\n"));
242 }
243 return rc;
244 }
245
246 bool CeCosTestSerial::Read (void *pBuf,unsigned int nSize,unsigned int &nRead)
247 {
248 bool rc=(TRUE==ReadFile((HANDLE)m_pHandle,pBuf,nSize,(LPDWORD)&nRead,0));
249 SaveError();
250 return rc;
251 }
252
253 bool CeCosTestSerial::Write(void *pBuf,unsigned int nSize,unsigned int &nWritten)
254 {
255 bool rc=(TRUE==WriteFile((HANDLE)m_pHandle,pBuf,nSize,(LPDWORD)&nWritten,0));
256 SaveError();
257 return rc;
258 }
259
260 bool CeCosTestSerial::ClearError()
261 {
262 DWORD dwErrors;
263 bool rc=(TRUE==ClearCommError(HANDLE(m_pHandle),&dwErrors,0));
264 if(dwErrors&CE_BREAK)TRACE(_T("The hardware detected a break condition.\n"));
265 if(dwErrors&CE_DNS)TRACE(_T("Windows 95 and Windows 98: A parallel device is not selected.\n"));
266 if(dwErrors&CE_FRAME)TRACE(_T("The hardware detected a framing error.\n"));
267 if(dwErrors&CE_IOE)TRACE(_T("An I/O error occurred during communications with the device.\n"));
268 if(dwErrors&CE_MODE)TRACE(_T("The requested mode is not supported, or the hFile parameter is invalid. If this value is specified, it is the only valid error.\n"));
269 if(dwErrors&CE_OOP)TRACE(_T("Windows 95 and Windows 98: A parallel device signaled that it is out of paper.\n"));
270 if(dwErrors&CE_OVERRUN)TRACE(_T("A character-buffer overrun has occurred. The next character is lost.\n"));
271 if(dwErrors&CE_PTO)TRACE(_T("Windows 95 and Windows 98: A time-out occurred on a parallel device.\n"));
272 if(dwErrors&CE_RXOVER)TRACE(_T("An input buffer overflow has occurred. There is either no room in the input buffer, or a character was received after the end-of-file (EOF) character.\n"));
273 if(dwErrors&CE_RXPARITY)TRACE(_T("The hardware detected a parity error.\n"));
274 if(dwErrors&CE_TXFULL)TRACE(_T("The application tried to transmit a character, but the output buffer was full.\n"));
275 return rc;
276 }
277
278 bool CeCosTestSerial::Flush (void)
279 {
280 bool rc=(TRUE==PurgeComm ((HANDLE)m_pHandle,PURGE_TXCLEAR|PURGE_RXCLEAR));
281 SaveError();
282 return rc;
283 }
284
285 String CeCosTestSerial::ErrString()
286 {
287 String str;
288 LPVOID lpMsgBuf;
289 FormatMessage(
290 FORMAT_MESSAGE_ALLOCATE_BUFFER |
291 FORMAT_MESSAGE_FROM_SYSTEM |
292 FORMAT_MESSAGE_IGNORE_INSERTS,
293 NULL,
294 m_nErr,
295 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
296 (LPTSTR) &lpMsgBuf,
297 0,
298 NULL
299 );
300 str=(LPCTSTR)lpMsgBuf;
301 // Free the buffer.
302 LocalFree( lpMsgBuf );
303 return str;
304 }
305
306 #else // UNIX
307
308 String CeCosTestSerial::ErrString()
309 {
310 return strerror(errno);
311 }
312
313 bool CeCosTestSerial::Close()
314 {
315 bool rc=m_pHandle && (-1!=close((int)m_pHandle));
316 m_pHandle=0;
317 return rc;
318 }
319
320 bool CeCosTestSerial::Open(LPCTSTR pszPort,int nBaud)
321 {
322 bool rc=false;
323 m_nBaud=nBaud,
324 m_strPort=pszPort;
325 int fd = open(pszPort,O_RDWR|O_NONBLOCK);
326 if (-1==fd) {
327 ERROR(_T("Failed to open port %s\n"),pszPort);
328 return false;
329 } else {
330 m_pHandle=(void *)fd;
331 if(ApplySettings()){
332 rc=true;
333 } else {
334 Close();
335 ERROR(_T("Failed to apply settings.\n"));
336 return false;
337 }
338 }
339 return rc;
340 }
341
342 bool CeCosTestSerial::ApplySettings()
343 {
344 struct termios buf, buf_verify;
345 int rate;
346
347 // Clear the two structures so we can make a binary comparison later on.
348 memset(&buf, 0, sizeof(buf));
349 memset(&buf_verify, 0, sizeof(buf_verify));
350
351 LPCTSTR arpszStopbits[3]={_T("1"),_T("1.5"),_T("2")};
352 TRACE(_T("Applysettings baud=%d bParity=%d stopbits=%s databits=%d\n"),
353 m_nBaud,
354 m_bParity,
355 arpszStopbits[m_nStopBits],
356 m_nDataBits);
357
358 switch(m_nBaud) {
359 case 110:
360 rate = B110;
361 break;
362 case 150:
363 rate = B150;
364 break;
365 case 300:
366 rate = B300;
367 break;
368 case 600:
369 rate = B600;
370 break;
371 case 1200:
372 rate = B1200;
373 break;
374 case 2400:
375 rate = B2400;
376 break;
377 case 4800:
378 rate = B4800;
379 break;
380 case 9600:
381 rate = B9600;
382 break;
383 case 19200:
384 rate = B19200;
385 break;
386 case 38400:
387 rate = B38400;
388 break;
389 case 57600:
390 rate = B57600;
391 break;
392 case 115200:
393 rate = B115200;
394 break;
395 default:
396 return false;
397 };
398
399 TRACE(_T("Changing configuration...\n"));
400
401 // Get current settings.
402 if (tcgetattr((int) m_pHandle, &buf)) {
403 fprintf(stderr, _T("Error: tcgetattr\n"));
404 return false;
405 }
406
407 // Reset to raw.
408 buf.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
409 |INLCR|IGNCR|ICRNL|IXON);
410 buf.c_oflag &= ~OPOST;
411 buf.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
412 buf.c_cflag &= ~(CSIZE|PARENB);
413 buf.c_cflag |= CS8;
414
415 // Set baud rate.
416 cfsetispeed(&buf, rate);
417 cfsetospeed(&buf, rate);
418
419 // Set data bits.
420 {
421 int data_bits[9] = {0, 0, 0, 0, 0, CS5, CS6, CS7, CS8};
422
423 buf.c_cflag &= ~CSIZE;
424 buf.c_cflag |= data_bits[m_nDataBits];
425 }
426
427 // Set stop bits.
428 {
429 buf.c_cflag &= ~CSTOPB;
430 if (ONE_STOP_BIT != m_nStopBits)
431 buf.c_cflag |= CSTOPB;
432 }
433
434 // Set parity.
435 {
436 buf.c_cflag &= ~(PARENB | PARODD); // no parity.
437 if (m_bParity) // even parity.
438 buf.c_cflag |= PARENB;
439 }
440
441 // Set the new settings
442 if (tcsetattr((int) m_pHandle, TCSADRAIN, &buf)) {
443 fprintf(stderr, _T("Error: tcsetattr\n"));
444 return false;
445 }
446
447 // Now read back the settings. On SunOS tcsetattr only returns
448 // error if _all_ settings fail. If just a few settings are not
449 // supported, the call returns true while the hardware is set to a
450 // combination of old and new settings.
451 if (tcgetattr((int) m_pHandle, &buf_verify)) {
452 fprintf(stderr, _T("Error: tcgetattr\n"));
453 return false;
454 }
455 if (memcmp(&buf, &buf_verify, sizeof(buf))) {
456 fprintf(stderr, _T("Error: termios verify failed\n"));
457 return false;
458 }
459
460 // A slight delay to allow things to settle.
461 Sleep(10);
462
463 TRACE(_T("Done.\n"));
464
465 return true;
466 }
467
468 bool CeCosTestSerial::Flush (void)
469 {
470 return 0==tcflush((int) m_pHandle, TCIOFLUSH);
471 }
472
473 bool CeCosTestSerial::Read (void *pBuf,unsigned int nSize,unsigned int &nRead)
474 {
475
476 if (!m_bBlockingReads) {
477 nRead = 0;
478 int n = read((int)m_pHandle, pBuf, nSize);
479 if (-1 == n) {
480 if (EAGAIN == errno)
481 return true;
482 ERROR(_T("Read failed: %d\n"), errno);
483 return false;
484 }
485 nRead = n;
486 return true;
487 }
488
489 // Blocking reads: emulate the Windows semantics:
490 // If m_nTotalReadTimeout elapses before we see the first TCHAR,
491 // return.
492 // If m_nInterCharReadTimeout elapses after reading any
493 // subsequent TCHAR, return.
494
495 fd_set rfds;
496 FD_ZERO(&rfds);
497 FD_SET((int)m_pHandle, &rfds);
498
499 // Start with total timeout.
500 struct timeval tv;
501 tv.tv_sec = m_nTotalReadTimeout / 1000;
502 tv.tv_usec = (m_nTotalReadTimeout % 1000) * 1000;
503
504 unsigned char* pData = (unsigned char*) pBuf;
505 nRead = 0;
506 while (nSize) {
507 switch(select((int)m_pHandle + 1, &rfds, NULL, NULL, &tv)) {
508 case 1:
509 {
510 int n = read((int)m_pHandle, pData, nSize);
511 if (-1 == n && EAGAIN != errno) {
512 ERROR(_T("Read failed: %d\n"), errno);
513 return false; // FAILED
514 }
515 nRead += n;
516 pData += n;
517 nSize -= n;
518
519 // Now use inter-char timeout.
520 tv.tv_sec = m_nInterCharReadTimeout / 1000;
521 tv.tv_usec = (m_nInterCharReadTimeout % 1000) * 1000;
522 }
523 break;
524 case 0:
525 return true; // Timeout
526 case -1:
527 ERROR(_T("Select failed: %d\n"), errno);
528 return false;
529 }
530 }
531
532 return true;
533 }
534
535 bool CeCosTestSerial::Write(void *pBuf,unsigned int nSize,unsigned int &nWritten)
536 {
537 bool rc;
538 int n=write((int)m_pHandle,pBuf,nSize);
539 if(-1==n){
540 nWritten=0;
541 if (errno == EAGAIN)
542 rc = true;
543 else
544 rc=false;
545 } else {
546 nWritten=n;
547 rc=true;
548 }
549 return rc;
550 }
551
552 bool CeCosTestSerial::ClearError()
553 {
554 return false;
555 }
556
557 #endif