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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [tools/] [src/] [tools/] [Utils/] [common/] [eCosSerial.cpp] - Blame information for rev 574

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

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

powered by: WebSVN 2.1.0

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