1 //+----------------------------------------------------------------------------
11 // Created: 12 Jan 2000
13 //+----------------------------------------------------------------------------
18 #include <sys/types.h>
30 //+----------------------------------------------------------------------------
32 // Function: CSerialPort
40 // History: sgasch Created Header 12 Jan 2000
42 //+----------------------------------------------------------------------------
43 CSerialPort::CSerialPort(void)
45 CSerialPort("/dev/cuaa0");
49 //+----------------------------------------------------------------------------
51 // Function: CSerialPort
55 // Arguments: char *szDevice
59 // History: sgasch Created Header 12 Jan 2000
61 //+----------------------------------------------------------------------------
62 CSerialPort::CSerialPort(char *szDevice)
65 // Precondition: the path of the serial port device passed in is valid.
67 ASSERT(GOOD_PTR(szDevice));
68 if (!GOOD_PTR(szDevice))
70 Trace("CSerialPort: Bad device argument, aborting.\n");
75 // Initialize identifiers
79 _fInitialized = false;
83 // Attempt to setup the serial line parameters.
85 if (false == SetupLine(szDevice))
87 Trace("CSerialPort: Could not setup line.\n");
99 //+----------------------------------------------------------------------------
101 // Function: CSerialPort
109 // History: sgasch Created Header 12 Jan 2000
111 //+----------------------------------------------------------------------------
112 CSerialPort::~CSerialPort(void)
114 _fInitialized = false;
117 // Close the file descriptor if it is currently open.
125 //+----------------------------------------------------------------------------
127 // Function: SetTimeout
131 // Arguments: int iNewTimeout
135 // History: sgasch Created Header 12 Jan 2000
137 //+----------------------------------------------------------------------------
138 void CSerialPort::SetTimeout(int iNewTimeout)
140 ASSERT(iNewTimeout >= 0);
141 _iTimeoutSec = iNewTimeout;
144 //+----------------------------------------------------------------------------
146 // Function: GetTimeout
154 // History: sgasch Created Header 12 Jan 2000
156 //+----------------------------------------------------------------------------
157 int CSerialPort::GetTimeout(void)
159 return(_iTimeoutSec);
162 //+----------------------------------------------------------------------------
168 // Arguments: BYTE *buf,
173 // History: sgasch Created Header 12 Jan 2000
175 //+----------------------------------------------------------------------------
176 bool CSerialPort::Read(BYTE *buf, int iNumBytes)
178 int iStatus = -1; // status returned from read call
179 int iBytesRead = 0; // number of bytes read so far
180 BYTE *bData = buf; // buffer to read into
181 int iRemainingBytes; // number of bytes remaining to read
185 // Precondition: the byte pointer is valid and we are initialized.
189 Trace("Read: Bad input argument, aborting.\n");
195 // Loop whie we have not yet read the full message.
199 iRemainingBytes = iNumBytes - iBytesRead;
200 iStatus = read(_iFd, bData, iRemainingBytes);
205 // The read failed. This might be becase we are reading
206 // too fast and there is no data on the port. In this
207 // case we will sleep for a second to allow the camera to
208 // fill the input buffer before we read again. If this is
209 // not the case we have a read error.
213 Trace("Read: read error on the serial port.\n");
219 if (iTimeout >= _iTimeoutSec)
221 Trace("Read: timeout waiting for data on serial port.\n");
231 // The read succeeded but it still might not have gotten the
232 // full message. We can find out by checking the return value
235 iBytesRead += iStatus;
240 while(iBytesRead < iNumBytes);
241 ASSERT(iBytesRead == iNumBytes);
249 //+----------------------------------------------------------------------------
255 // Arguments: BYTE *buf,
260 // History: sgasch Created Header 12 Jan 2000
262 //+----------------------------------------------------------------------------
263 bool CSerialPort::Write(BYTE *buf, int iNumBytes)
265 int iStatus = -1; // status returned from write call
266 int iBytesWritten = 0; // number of bytes written so far
267 BYTE *bData = buf; // data to write
268 int iRemainingBytes; // number of bytes remaining write
272 // Precondition: the byte pointer is valid and we are initialized.
276 Trace("Write: Bad input argument, aborting.\n");
282 // Loop while we have not yet sent the full message to the port.
286 iRemainingBytes = iNumBytes - iBytesWritten;
287 iStatus = write(_iFd, bData, iRemainingBytes);
291 // An error occurred. If we get EAGAIN in errno it means that
292 // the port can't take our write right now, we'll sleep and try
293 // again next loop. Otherwise we have a write error.
297 Trace("Write: write error on the serial port.\n");
303 if (iTimeout >= _iTimeoutSec)
305 Trace("Write: timeout on the serial port.");
315 // Write was successful but it still not have written the full
316 // message. We find out by seeing how many bytes it did write.
318 iBytesWritten += iStatus;
323 while (iBytesWritten < iNumBytes);
324 ASSERT(iBytesWritten == iNumBytes);
332 //+----------------------------------------------------------------------------
334 // Function: SetBaudrate
338 // Arguments: int iBps
342 // History: sgasch Created Header 12 Jan 2000
344 //+----------------------------------------------------------------------------
345 bool CSerialPort::SetBaudrate(int iBps)
347 struct termios sTerm; // serial port configuration data
350 // Preconditions: the baud rate is supported by the camera.
352 if ((iBps != 9600) &&
358 Trace("SetBaudRate: illegal rate.\n");
363 // Get the terios structure of the file descriptor we are using to
364 // talk to the com port... we want to set up in a way that the
365 // camera can understand.
367 if (tcgetattr(_iFd, &sTerm) < 0)
369 Trace("SetBaudRate: could not get termios struct for serial fd."
376 // Set the input and output baud rates to the new setting.
378 if (cfsetispeed(&sTerm, iBps) < 0)
380 Trace("SetBaudRate: could not set baud rate.\n");
385 if (cfsetospeed(&sTerm, iBps) < 0)
387 Trace("SetBaudRate: could not set baud rate.\n");
393 // Make it "raw" (no cooked I/O)
400 sTerm.c_cflag |= CS8;
405 sTerm.c_cflag &= ~CSTOPB;
408 // Non-canonical mode settings
410 sTerm.c_cc[VTIME] = 5;
411 sTerm.c_cc[VMIN] = 255;
414 // Apply these termios settings.
416 if (tcsetattr(_iFd, 0, &sTerm) < 0)
418 Trace("SetBaudRate: could not set termios struct for serial fd."
432 //+----------------------------------------------------------------------------
434 // Function: GetBaudrate
442 // History: sgasch Created Header 12 Jan 2000
444 //+----------------------------------------------------------------------------
445 int CSerialPort::GetBaudrate(void)
450 //+----------------------------------------------------------------------------
452 // Function: SetupLine (private)
456 // Arguments: char *szDevice
460 // History: sgasch Created Header 12 Jan 2000
462 //+----------------------------------------------------------------------------
463 bool CSerialPort::SetupLine(char *szDevice)
465 int iStatus = -1; // status from open call
466 struct termios sTerm; // line characteristics struct
469 // TODO: UUCP locking code here?
473 // Open the serial port in read/write mode.
475 iStatus = open(szDevice, O_RDWR);
478 Trace("SetupSerialLine: Unable to open serial port.\n");
485 // Use fcntl to tell the system we do not want to block on I/O from
486 // the file descriptor. All read/write calls are asynchronous.
488 if (fcntl(iStatus, F_SETFL, O_NONBLOCK) < 0)
490 Trace("SetupSerialLine: fcntl call failed, cannot use non-blocking "
497 // Get the terios structure of the file descriptor we are using to talk
498 // to the com port... we want to set up in a way that the camera can
501 if (tcgetattr(iStatus, &sTerm) < 0)
503 Trace("SetupSerialLine: could not get termios struct for serial "
510 // Make it "raw" (no cooked I/O).
512 (void) cfmakeraw(&sTerm);
515 // The camera defaults to 9600 bps.
517 if (false == SetBaudrate(9600))
519 Trace("SetupLine: could not set baud rate to 9600?\n");
527 sTerm.c_cflag |= CS8;
532 sTerm.c_cflag &= ~CSTOPB;
535 // Don't echo back anything at all...
537 sTerm.c_lflag &= ~ECHO;
538 sTerm.c_lflag &= ~ECHOE;
539 sTerm.c_lflag &= ~ECHOCTL;
540 sTerm.c_lflag &= ~ECHOKE;
541 sTerm.c_lflag &= ~ECHONL;
542 sTerm.c_lflag &= ~ECHOPRT;
545 // There are no special control characters like KILL or ERASE...
547 sTerm.c_lflag &= ~IEXTEN;
548 sTerm.c_lflag &= ~ICANON;
551 // Don't send stop/start characters (flow control)
553 sTerm.c_iflag &= ~IXOFF;
556 // Non-canonical mode settings
558 sTerm.c_cc[VTIME] = 5;
559 sTerm.c_cc[VMIN] = 255;
562 // Apply these termios settings.
564 if (tcsetattr(iStatus, 0, &sTerm) < 0)
566 Trace("SetupSerialLine: could not set termios struct for serial "
580 bool CSerialPort::WriteByte(BYTE bData)
584 return(Write(&x, 1));