OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [host/] [tools/] [Utils/] [common/] [eCosSerial.cpp] - Blame information for rev 790

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.