4 * Asynchronous serial I/O channel class implementation.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.28 2004/02/22 04:06:47 ykiryanov
31 * ifdef'd all functions because BeOS don't support it
33 * Revision 1.27 2002/11/02 00:32:21 robertj
34 * Further fixes to VxWorks (Tornado) port, thanks Andreas Sikkema.
36 * Revision 1.26 2002/10/17 13:44:27 robertj
37 * Port to RTEMS, thanks Vladimir Nesic.
39 * Revision 1.25 2002/10/10 04:43:44 robertj
40 * VxWorks port, thanks Martijn Roest
42 * Revision 1.24 2002/03/27 06:42:16 robertj
43 * Implemented the DTR etc functions and ttya/ttyb strings for sunos,
44 * thanks tommi.korhonen@insta.fi & Raimo Ruokonen <rruokonen@koti.soon.fi>
46 * Revision 1.23 2001/09/10 03:03:36 robertj
47 * Major change to fix problem with error codes being corrupted in a
48 * PChannel when have simultaneous reads and writes in threads.
50 * Revision 1.22 2001/08/11 15:38:43 rogerh
51 * Add Mac OS Carbon changes from John Woods <jfw@jfwhome.funhouse.com>
53 * Revision 1.21 2001/01/04 17:57:41 rogerh
54 * Fix a cut and past error in my previous commit
56 * Revision 1.20 2001/01/04 10:28:07 rogerh
57 * FreeBSD does not set the Baud Rate with c_cflags. Add the 'BSD' way
59 * Revision 1.19 2001/01/03 10:56:01 rogerh
60 * CBAUD is not defined on FreeBSD.
62 * Revision 1.18 2000/12/29 07:36:18 craigs
63 * Finally got working correctly!
65 * Revision 1.17 2000/11/14 14:56:24 rogerh
66 * Fix #define parameters (fd should be just f)
68 * Revision 1.16 2000/11/14 14:52:32 rogerh
69 * Fix SET/GET typo error
71 * Revision 1.15 2000/11/12 23:30:41 craigs
72 * Fixed problems with serial port configuration
74 * Revision 1.14 2000/06/21 01:01:22 robertj
75 * AIX port, thanks Wolfgang Platzer (wolfgang.platzer@infonova.at).
77 * Revision 1.13 2000/04/09 18:19:23 rogerh
78 * Add my changes for NetBSD support.
80 * Revision 1.12 2000/04/06 12:11:32 rogerh
81 * MacOS X support submitted by Kevin Packard
83 * Revision 1.11 2000/03/08 12:17:09 rogerh
86 * Revision 1.10 1998/12/21 06:08:08 robertj
87 * Fixed warning on solaris x86 GNU system.
89 * Revision 1.9 1998/11/30 21:51:54 robertj
90 * New directory structure.
92 * Revision 1.8 1998/11/24 09:39:14 robertj
95 * Revision 1.7 1998/09/24 04:12:17 robertj
96 * Added open software license.
100 #pragma implementation "serchan.h"
101 #pragma implementation "modem.h"
106 #include <sys/ioctl.h>
109 #define TCSETATTR(f,t) tcsetattr(f,TCSANOW,t)
110 #define TCGETATTR(f,t) tcgetattr(f,t)
112 #elif defined(P_FREEBSD) || defined(P_OPENBSD) || defined (P_NETBSD) || defined(P_MACOSX) || defined(P_MACOS) || defined(P_RTEMS)
113 #include <sys/ttycom.h>
114 #define TCGETA TIOCGETA
115 #define TCSETAW TIOCSETAW
117 #elif defined(P_SUN4)
118 #include <sys/termio.h>
119 extern "C" int ioctl(int, int, void *);
121 #elif defined (P_AIX)
122 #include <sys/termio.h>
127 #define TCSETATTR(f,t) ::ioctl(f,TCSETAW,t)
131 #define TCGETATTR(f,t) ::ioctl(f,TCGETA,t)
134 //#define BINARY_LOCK 1
135 #define LOCK_PREFIX "/var/spool/uucp/LCK.."
136 #define DEV_PREFIX "/dev/"
138 #define PORTLISTENV "PWLIB_SERIALPORTS"
139 #define DEV_PREFIX "/dev/"
141 #include "../common/serial.cxx"
143 ////////////////////////////////////////////////////////////////
148 void PSerialChannel::Construct()
150 // set control modes: 9600, N, 8, 1, local line
153 parityBits
= NoParity
;
156 #if defined(P_VXWORKS) || defined (__BEOS__)
157 PAssertAlways(PUnimplementedFunction
);
160 // set input mode: ignore breaks, ignore parity errors, do not strip chars,
161 // no CR/NL conversion, no case conversion, no XON/XOFF control,
163 Termio
.c_iflag
= IGNBRK
| IGNPAR
;
164 Termio
.c_cflag
= CS8
| CSTOPB
| CREAD
| CLOCAL
;
166 #if defined(P_FREEBSD) || defined(P_OPENBSD) || defined (P_NETBSD) || defined(P_MACOSX) || defined(P_MACOS)
167 Termio
.c_ispeed
= Termio
.c_ospeed
= B9600
;
169 Termio
.c_cflag
|= B9600
;
172 // set output mode: no post process output,
175 // set line discipline
181 BOOL
PSerialChannel::Close()
183 #if defined(P_VXWORKS) || defined (__BEOS__)
184 PAssertAlways(PUnimplementedFunction
);
186 if (os_handle
>= 0) {
188 // delete the lockfile
189 PFile::Remove(PString(LOCK_PREFIX
) + channelName
);
191 // restore the original terminal settings
192 TCSETATTR(os_handle
, &oldTermio
);
195 return PChannel::Close();
200 BOOL
PSerialChannel::Open(const PString
& port
,
205 FlowControl inputFlow
,
206 FlowControl outputFlow
)
208 // if the port is already open, close it
212 // // check prefix of name
213 // if (port.Left(PORT_PREFIX_LEN) != PORT_PREFIX) {
214 // lastError = BadParameter;
219 // int portnum = (port.Right(port.GetLength()-PORT_PREFIX_LEN)).AsInteger();
220 // if ((portnum < PORT_START) || (portnum >= (PORT_START + PORT_COUNT))) {
221 // lastError = BadParameter;
225 // save the port name
228 #if defined(P_VXWORKS) || defined (__BEOS__)
229 PAssertAlways(PUnimplementedFunction
);
233 // construct lock filename
234 PString lockfilename
= PString(LOCK_PREFIX
) + port
;
236 // if the file exists, probe the process to see if it is still running
237 if (PFile::Exists(lockfilename
)) {
238 PFile
lockfile(lockfilename
, PFile::ReadOnly
);
242 lockfile
.Read(&lock_pid
, sizeof(lock_pid
));
244 char lock_pid_str
[20];
245 lockfile
.Read(&lock_pid_str
, 20);
246 lock_pid
= atoi(lock_pid_str
);
249 // if kill returns 0, then the port is in use
250 if (kill(lock_pid
, 0) == 0)
251 return SetErrorValues(DeviceInUse
, EBUSY
);
253 // remove the lock file
257 // create new lockfile with our PID
258 PFile
lockfile(lockfilename
, PFile::WriteOnly
, PFile::Create
);
261 lockfile
.Write(&pid
, sizeof(pid
));
267 // attempt to open the device
268 PString device_name
= PString(DEV_PREFIX
) + port
;
269 if ((os_handle
= ::open((const char *)device_name
, O_RDWR
|O_NONBLOCK
|O_NOCTTY
)) < 0) {
270 ConvertOSError(os_handle
);
275 // save the channel name
278 // save the current port setup
279 TCGETATTR(os_handle
, &oldTermio
);
281 // set the default paramaters
282 TCSETATTR(os_handle
, &Termio
);
284 // now set the mode that was passed in
285 if (!SetSpeed(speed
) ||
286 !SetDataBits(data
) ||
287 !SetParity(parity
) ||
288 !SetStopBits(stop
) ||
289 !SetInputFlowControl(inputFlow
) ||
290 !SetOutputFlowControl(outputFlow
)) {
296 ::fcntl(os_handle
, F_SETFD
, 1);
303 BOOL
PSerialChannel::SetSpeed(DWORD newBaudRate
)
305 if (newBaudRate
== baudRate
)
311 #if defined(P_VXWORKS) || defined (__BEOS__)
312 PAssertAlways(PUnimplementedFunction
);
318 switch(newBaudRate
) {
419 // save new baud rate
420 baudRate
= newBaudRate
;
422 #if defined(P_FREEBSD) || defined(P_OPENBSD) || defined (P_NETBSD) || defined(P_MACOSX) || defined(P_MACOS)
424 Termio
.c_ispeed
= baud
;
425 Termio
.c_ospeed
= baud
;
428 Termio
.c_cflag
&= ~CBAUD
;
429 Termio
.c_cflag
|= baud
;
435 // initialise the port
436 return ConvertOSError(TCSETATTR(os_handle
, &Termio
));
442 BOOL
PSerialChannel::SetDataBits(BYTE data
)
444 if (data
== dataBits
)
447 #if defined(P_VXWORKS) || defined (__BEOS__)
448 PAssertAlways(PUnimplementedFunction
);
487 // set the new number of data bits
489 Termio
.c_cflag
&= ~CSIZE
;
490 Termio
.c_cflag
|= flags
;
495 return ConvertOSError(TCSETATTR(os_handle
, &Termio
));
500 BOOL
PSerialChannel::SetParity(Parity parity
)
502 if (parity
== parityBits
)
505 #if defined(P_VXWORKS) || defined (__BEOS__)
506 PAssertAlways(PUnimplementedFunction
);
514 flags
= PARODD
| PARENB
;
538 // set the new parity
540 Termio
.c_cflag
&= ~(PARENB
|PARODD
);
541 Termio
.c_cflag
|= flags
;
543 return ConvertOSError(TCSETATTR(os_handle
, &Termio
));
548 BOOL
PSerialChannel::SetStopBits(BYTE stop
)
550 if (stop
== stopBits
)
553 #if defined(P_VXWORKS) || defined (__BEOS__)
554 PAssertAlways(PUnimplementedFunction
);
579 // set the new number of stop bits
581 Termio
.c_cflag
&= ~CSTOPB
;
582 Termio
.c_cflag
|= flags
;
584 return ConvertOSError(TCSETATTR(os_handle
, &Termio
));
589 DWORD
PSerialChannel::GetSpeed() const
594 BYTE
PSerialChannel::GetStopBits() const
599 BYTE
PSerialChannel::GetDataBits() const
604 PSerialChannel::Parity
PSerialChannel::GetParity() const
609 BOOL
PSerialChannel::SetInputFlowControl(FlowControl
)
615 PSerialChannel::FlowControl
PSerialChannel::GetInputFlowControl() const
617 return NoFlowControl
;
621 BOOL
PSerialChannel::SetOutputFlowControl(FlowControl
)
627 PSerialChannel::FlowControl
PSerialChannel::GetOutputFlowControl() const
629 return NoFlowControl
;
633 void PSerialChannel::SetDTR(BOOL mode
)
635 #if defined(P_VXWORKS) || defined (__BEOS__)
636 PAssertAlways(PUnimplementedFunction
);
640 ioctl(os_handle
,TIOCMGET
,&flags
); // get the bits
644 ioctl(os_handle
,TIOCMSET
,&flags
); // set back
647 ALTERNATE IMPLEMENTATION?
648 Uses "Local Mode" bits?
650 ioctl(os_handle, TIOCSDTR, 0);
652 ioctl(os_handle, TIOCCDTR, 0);
659 void PSerialChannel::SetRTS(BOOL mode
)
661 #if defined(P_VXWORKS) || defined (__BEOS__)
662 PAssertAlways(PUnimplementedFunction
);
666 ioctl(os_handle
,TIOCMGET
,&flags
); // get the bits
670 ioctl(os_handle
,TIOCMSET
,&flags
); // set back
676 void PSerialChannel::SetBreak(BOOL mode
)
678 #if defined(P_VXWORKS) || defined (__BEOS__)
679 PAssertAlways(PUnimplementedFunction
);
683 ioctl(os_handle
, TIOCSBRK
, 0);
685 ioctl(os_handle
, TIOCCBRK
, 0);
691 BOOL
PSerialChannel::GetCTS()
693 #if defined(P_VXWORKS) || defined (__BEOS__)
694 PAssertAlways(PUnimplementedFunction
);
699 ioctl(os_handle
,TIOCMGET
,&flags
); // get the bits
700 return (flags
&TIOCM_CTS
)?TRUE
:FALSE
;
706 BOOL
PSerialChannel::GetDSR()
708 #if defined(P_VXWORKS) || defined (__BEOS__)
709 PAssertAlways(PUnimplementedFunction
);
715 ioctl(os_handle
,TIOCMGET
,&flags
); // get the bits
716 return (flags
&TIOCM_DSR
)?TRUE
:FALSE
;
722 BOOL
PSerialChannel::GetDCD()
724 #if defined(P_VXWORKS) || defined (__BEOS__)
725 PAssertAlways(PUnimplementedFunction
);
731 ioctl(os_handle
,TIOCMGET
,&flags
); // get the bits
732 return (flags
&TIOCM_CD
)?TRUE
:FALSE
;
738 BOOL
PSerialChannel::GetRing()
740 #if defined(P_VXWORKS) || defined (__BEOS__)
741 PAssertAlways(PUnimplementedFunction
);
747 ioctl(os_handle
,TIOCMGET
,&flags
); // get the bits
748 return (flags
&TIOCM_RNG
)?TRUE
:FALSE
;
754 PStringList
PSerialChannel::GetPortNames()
758 char * env
= getenv(PORTLISTENV
);
761 PStringArray tokens
= str
.Tokenise(" ,\t", FALSE
);
763 for (i
= 0; i
< tokens
.GetSize(); i
++)
764 ports
.AppendString(tokens
[i
]);
766 #if defined(__sun) && defined (__sparc)
767 ports
.AppendString(PString("ttya"));
768 ports
.AppendString(PString("ttyb"));
770 ports
.AppendString(PString("ttyS0"));
771 ports
.AppendString(PString("ttyS1"));
772 ports
.AppendString(PString("ttyS2"));
773 ports
.AppendString(PString("ttyS3"));
781 // End of File ///////////////////////////////////////////////////////////////