Uncommented beaudio code
[pwlib.git] / src / ptlib / unix / serchan.cxx
blob901849b2c218afb54ef006a6d9b2c5d4c76da5a7
1 /*
2 * serchan.cxx
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
18 * under the License.
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): ______________________________________.
29 * $Log$
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
84 * Add OpenBSD support
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
93 * FreeBSD port.
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"
103 #include <ptlib.h>
104 #include <fcntl.h>
105 #include <signal.h>
106 #include <sys/ioctl.h>
108 #if defined(P_LINUX)
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>
123 #endif
126 #ifndef TCSETATTR
127 #define TCSETATTR(f,t) ::ioctl(f,TCSETAW,t)
128 #endif
130 #ifndef TCGETATTR
131 #define TCGETATTR(f,t) ::ioctl(f,TCGETA,t)
132 #endif
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 ////////////////////////////////////////////////////////////////
145 // PSerialChannel
148 void PSerialChannel::Construct()
150 // set control modes: 9600, N, 8, 1, local line
151 baudRate = 9600;
152 dataBits = 8;
153 parityBits = NoParity;
154 stopBits = 1;
156 #if defined(P_VXWORKS) || defined (__BEOS__)
157 PAssertAlways(PUnimplementedFunction);
158 #else
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,
162 // no start/stop
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;
168 #else
169 Termio.c_cflag |= B9600;
170 #endif
172 // set output mode: no post process output,
173 Termio.c_oflag = 0;
175 // set line discipline
176 Termio.c_lflag = 0;
178 #endif // P_VXWORKS
181 BOOL PSerialChannel::Close()
183 #if defined(P_VXWORKS) || defined (__BEOS__)
184 PAssertAlways(PUnimplementedFunction);
185 #else
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();
196 #endif // P_VXWORKS
200 BOOL PSerialChannel::Open(const PString & port,
201 DWORD speed,
202 BYTE data,
203 Parity parity,
204 BYTE stop,
205 FlowControl inputFlow,
206 FlowControl outputFlow)
208 // if the port is already open, close it
209 if (IsOpen())
210 Close();
212 // // check prefix of name
213 // if (port.Left(PORT_PREFIX_LEN) != PORT_PREFIX) {
214 // lastError = BadParameter;
215 // return FALSE;
216 // }
218 // // check suffix
219 // int portnum = (port.Right(port.GetLength()-PORT_PREFIX_LEN)).AsInteger();
220 // if ((portnum < PORT_START) || (portnum >= (PORT_START + PORT_COUNT))) {
221 // lastError = BadParameter;
222 // return FALSE;
223 // }
225 // save the port name
226 channelName = port;
228 #if defined(P_VXWORKS) || defined (__BEOS__)
229 PAssertAlways(PUnimplementedFunction);
230 return FALSE;
231 #else
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);
240 int lock_pid;
241 #ifdef BINARY_LOCK
242 lockfile.Read(&lock_pid, sizeof(lock_pid));
243 #else
244 char lock_pid_str[20];
245 lockfile.Read(&lock_pid_str, 20);
246 lock_pid = atoi(lock_pid_str);
247 #endif
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
254 lockfile.Remove();
257 // create new lockfile with our PID
258 PFile lockfile(lockfilename, PFile::WriteOnly, PFile::Create);
259 int pid = getpid();
260 #ifdef BINARY_LOCK
261 lockfile.Write(&pid, sizeof(pid));
262 #else
263 lockfile << pid;
264 #endif
265 lockfile.Close();
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);
271 Close();
272 return FALSE;
275 // save the channel name
276 channelName = port;
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)) {
291 errno = EINVAL;
292 ConvertOSError(-1);
293 return FALSE;
296 ::fcntl(os_handle, F_SETFD, 1);
298 #endif // P_VXWORKS
300 return TRUE;
303 BOOL PSerialChannel::SetSpeed(DWORD newBaudRate)
305 if (newBaudRate == baudRate)
306 return TRUE;
308 if (os_handle < 0)
309 return TRUE;
311 #if defined(P_VXWORKS) || defined (__BEOS__)
312 PAssertAlways(PUnimplementedFunction);
313 return FALSE;
314 #else
316 int baud;
318 switch(newBaudRate) {
319 #ifdef B50
320 case 50:
321 baud = B50;
322 break;
323 #endif
324 #ifdef B75
325 case 75:
326 baud = B75;
327 break;
328 #endif
329 #ifdef B110
330 case 110:
331 baud = B110;
332 break;
333 #endif
334 #ifdef B134
335 case 134:
336 baud = B134;
337 break;
338 #endif
339 #ifdef B150
340 case 150:
341 baud = B150;
342 break;
343 #endif
344 #ifdef B200
345 case 200:
346 baud = B200;
347 break;
348 #endif
349 #ifdef B300
350 case 300:
351 baud = B300;
352 break;
353 #endif
354 #ifdef B600
355 case 600:
356 baud = B600;
357 break;
358 #endif
359 #ifdef B1200
360 case 1200:
361 baud = B1200;
362 break;
363 #endif
364 #ifdef B1800
365 case 1800:
366 baud = B1800;
367 break;
368 #endif
369 #ifdef B2400
370 case 2400:
371 baud = B2400;
372 break;
373 #endif
374 #ifdef B4800
375 case 4800:
376 baud = B4800;
377 break;
378 #endif
379 #ifdef B9600
380 case 9600:
381 baud = B9600;
382 break;
383 #endif
384 #ifdef B19200
385 case 19200:
386 baud = B19200;
387 break;
388 #endif
389 #ifdef B38400
390 case 38400:
391 baud = B38400;
392 break;
393 #endif
394 #ifdef B57600
395 case 57600:
396 baud = B57600;
397 break;
398 #endif
399 #ifdef B115200
400 case 115200:
401 baud = B115200;
402 break;
403 #endif
404 #ifdef B230400
405 case 230400:
406 baud = B230400;
407 break;
408 #endif
409 default:
410 baud = -1;
413 if (baud == -1) {
414 errno = EINVAL;
415 ConvertOSError(-1);
416 return FALSE;
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)
423 // The BSD way
424 Termio.c_ispeed = baud;
425 Termio.c_ospeed = baud;
426 #else
427 // The Linux way
428 Termio.c_cflag &= ~CBAUD;
429 Termio.c_cflag |= baud;
430 #endif
432 if (os_handle < 0)
433 return TRUE;
435 // initialise the port
436 return ConvertOSError(TCSETATTR(os_handle, &Termio));
438 #endif // P_VXWORKS
442 BOOL PSerialChannel::SetDataBits(BYTE data)
444 if (data == dataBits)
445 return TRUE;
447 #if defined(P_VXWORKS) || defined (__BEOS__)
448 PAssertAlways(PUnimplementedFunction);
449 return FALSE;
450 #else
452 int flags;
454 switch (data) {
455 #ifdef CS5
456 case 5:
457 flags = CS5;
458 break;
459 #endif
460 #ifdef CS6
461 case 6:
462 flags = CS6;
463 break;
464 #endif
465 #ifdef CS7
466 case 7:
467 flags = CS7;
468 break;
469 #endif
470 #ifdef CS8
471 case 8:
472 case 0: // default
473 flags = CS8;
474 break;
475 #endif
476 default:
477 flags = -1;
478 break;
481 if (flags == 0) {
482 errno = EINVAL;
483 ConvertOSError(-1);
484 return FALSE;
487 // set the new number of data bits
488 dataBits = data;
489 Termio.c_cflag &= ~CSIZE;
490 Termio.c_cflag |= flags;
492 if (os_handle < 0)
493 return TRUE;
495 return ConvertOSError(TCSETATTR(os_handle, &Termio));
497 #endif // P_VXWORKS
500 BOOL PSerialChannel::SetParity(Parity parity)
502 if (parity == parityBits)
503 return TRUE;
505 #if defined(P_VXWORKS) || defined (__BEOS__)
506 PAssertAlways(PUnimplementedFunction);
507 return FALSE;
508 #else
510 int flags;
512 switch (parity) {
513 case OddParity:
514 flags = PARODD | PARENB;
515 break;
516 case EvenParity:
517 flags = PARENB;
518 case NoParity:
519 case DefaultParity:
520 flags = IGNPAR;
521 break;
523 case MarkParity:
524 case SpaceParity:
525 default:
526 flags = -1;
529 if (flags < 0) {
530 errno = EINVAL;
531 ConvertOSError(-1);
532 return FALSE;
535 if (os_handle < 0)
536 return TRUE;
538 // set the new parity
539 parityBits = parity;
540 Termio.c_cflag &= ~(PARENB|PARODD);
541 Termio.c_cflag |= flags;
543 return ConvertOSError(TCSETATTR(os_handle, &Termio));
545 #endif // P_VXWORKS
548 BOOL PSerialChannel::SetStopBits(BYTE stop)
550 if (stop == stopBits)
551 return TRUE;
553 #if defined(P_VXWORKS) || defined (__BEOS__)
554 PAssertAlways(PUnimplementedFunction);
555 return FALSE;
556 #else
558 int flags;
560 switch (stop) {
561 case 2:
562 flags = CSTOPB;
563 break;
564 default:
565 case 1:
566 flags = 0;
567 break;
570 if (flags < 0) {
571 errno = EINVAL;
572 ConvertOSError(-1);
573 return FALSE;
576 if (os_handle < 0)
577 return TRUE;
579 // set the new number of stop bits
580 stopBits = stop;
581 Termio.c_cflag &= ~CSTOPB;
582 Termio.c_cflag |= flags;
584 return ConvertOSError(TCSETATTR(os_handle, &Termio));
586 #endif // P_VXWORKS
589 DWORD PSerialChannel::GetSpeed() const
591 return baudRate;
594 BYTE PSerialChannel::GetStopBits() const
596 return stopBits;
599 BYTE PSerialChannel::GetDataBits() const
601 return dataBits;
604 PSerialChannel::Parity PSerialChannel::GetParity() const
606 return parityBits;
609 BOOL PSerialChannel::SetInputFlowControl(FlowControl)
611 return TRUE;
615 PSerialChannel::FlowControl PSerialChannel::GetInputFlowControl() const
617 return NoFlowControl;
621 BOOL PSerialChannel::SetOutputFlowControl(FlowControl)
623 return TRUE;
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);
637 #else
639 int flags = 0;
640 ioctl(os_handle,TIOCMGET,&flags); // get the bits
641 flags &= ~TIOCM_DTR;
642 if ( mode == TRUE )
643 flags |= TIOCM_DTR;
644 ioctl(os_handle,TIOCMSET,&flags); // set back
647 ALTERNATE IMPLEMENTATION?
648 Uses "Local Mode" bits?
649 if ( mode TRUE )
650 ioctl(os_handle, TIOCSDTR, 0);
651 else
652 ioctl(os_handle, TIOCCDTR, 0);
655 #endif // P_VXWORKS
659 void PSerialChannel::SetRTS(BOOL mode)
661 #if defined(P_VXWORKS) || defined (__BEOS__)
662 PAssertAlways(PUnimplementedFunction);
663 #else
665 int flags = 0;
666 ioctl(os_handle,TIOCMGET,&flags); // get the bits
667 flags &= ~TIOCM_RTS;
668 if ( mode == TRUE )
669 flags |= TIOCM_RTS;
670 ioctl(os_handle,TIOCMSET,&flags); // set back
672 #endif // P_VXWORKS
676 void PSerialChannel::SetBreak(BOOL mode)
678 #if defined(P_VXWORKS) || defined (__BEOS__)
679 PAssertAlways(PUnimplementedFunction);
680 #else
682 if (mode)
683 ioctl(os_handle, TIOCSBRK, 0);
684 else
685 ioctl(os_handle, TIOCCBRK, 0);
687 #endif // P_VXWORKS
691 BOOL PSerialChannel::GetCTS()
693 #if defined(P_VXWORKS) || defined (__BEOS__)
694 PAssertAlways(PUnimplementedFunction);
695 return FALSE;
696 #else
698 int flags = 0;
699 ioctl(os_handle,TIOCMGET,&flags); // get the bits
700 return (flags&TIOCM_CTS)?TRUE:FALSE;
702 #endif // P_VXWORKS
706 BOOL PSerialChannel::GetDSR()
708 #if defined(P_VXWORKS) || defined (__BEOS__)
709 PAssertAlways(PUnimplementedFunction);
710 return FALSE;
711 #else
713 int flags = 0;
715 ioctl(os_handle,TIOCMGET,&flags); // get the bits
716 return (flags&TIOCM_DSR)?TRUE:FALSE;
718 #endif // P_VXWORKS
722 BOOL PSerialChannel::GetDCD()
724 #if defined(P_VXWORKS) || defined (__BEOS__)
725 PAssertAlways(PUnimplementedFunction);
726 return FALSE;
727 #else
729 int flags = 0;
731 ioctl(os_handle,TIOCMGET,&flags); // get the bits
732 return (flags&TIOCM_CD)?TRUE:FALSE;
734 #endif // P_VXWORKS
738 BOOL PSerialChannel::GetRing()
740 #if defined(P_VXWORKS) || defined (__BEOS__)
741 PAssertAlways(PUnimplementedFunction);
742 return FALSE;
743 #else
745 int flags = 0;
747 ioctl(os_handle,TIOCMGET,&flags); // get the bits
748 return (flags&TIOCM_RNG)?TRUE:FALSE;
750 #endif // P_VXWORKS
754 PStringList PSerialChannel::GetPortNames()
756 PStringList ports;
758 char * env = getenv(PORTLISTENV);
759 if (env != NULL) {
760 PString str(env);
761 PStringArray tokens = str.Tokenise(" ,\t", FALSE);
762 PINDEX i;
763 for (i = 0; i < tokens.GetSize(); i++)
764 ports.AppendString(tokens[i]);
765 } else {
766 #if defined(__sun) && defined (__sparc)
767 ports.AppendString(PString("ttya"));
768 ports.AppendString(PString("ttyb"));
769 #else
770 ports.AppendString(PString("ttyS0"));
771 ports.AppendString(PString("ttyS1"));
772 ports.AppendString(PString("ttyS2"));
773 ports.AppendString(PString("ttyS3"));
774 #endif
777 return ports;
781 // End of File ///////////////////////////////////////////////////////////////