diff options
Diffstat (limited to 'tester/rt/stty.py')
-rw-r--r-- | tester/rt/stty.py | 567 |
1 files changed, 567 insertions, 0 deletions
diff --git a/tester/rt/stty.py b/tester/rt/stty.py new file mode 100644 index 0000000..d059b40 --- /dev/null +++ b/tester/rt/stty.py @@ -0,0 +1,567 @@ +# +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2013-2014 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Testing Consoles +# + +import os +import sys +import termios + +from rtemstoolkit import error +from rtemstoolkit import options +from rtemstoolkit import path + +def save(): + if not options.host_windows: + try: + sin = termios.tcgetattr(sys.stdin) + sout = termios.tcgetattr(sys.stdout) + serr = termios.tcgetattr(sys.stderr) + return sin, sout, serr + except: + pass + return None + +def restore(attributes): + if attributes is not None: + termios.tcsetattr(sys.stdin, termios.TCSANOW, attributes[0]) + termios.tcsetattr(sys.stdout, termios.TCSANOW, attributes[1]) + termios.tcsetattr(sys.stderr, termios.TCSANOW, attributes[2]) + +class tty: + + def __init__(self, dev): + if options.host_windows: + raise error.general('termios not support on host') + self.dev = dev + self.default_attr = None + self.fd = None + self.if_on = False + if options.host_windows: + raise error.general('TTY consoles not supported on Windows.') + if not path.exists(dev): + raise error.general('dev not found: %s' % (dev)) + try: + self.fd = open(dev, 'rw') + except IOError, ioe: + raise error.general('opening tty dev: %s: %s' % (dev, ioe)) + except: + raise error.general('opening tty dev: %s: unknown' % (dev)) + try: + self.default_attr = termios.tcgetattr(self.fd) + except: + raise error.general('cannot get termios attrs: %s' % (dev)) + self.attr = self.default_attr + + def __del__(self): + if self.fd and self.default_attr: + try: + self.fd.close() + except: + pass + + def __str__(self): + def _input(attr): + s = '' + if attr & termios.IGNBRK: + s += ' IGNBRK' + if attr & termios.BRKINT: + s += ' BRKINT' + if attr & termios.IGNPAR: + s += ' IGNPAR' + if attr & termios.PARMRK: + s += ' PARMRK' + if attr & termios.INPCK: + s += ' INPCK' + if attr & termios.ISTRIP: + s += ' ISTRIP' + if attr & termios.INLCR: + s += ' INLCR' + if attr & termios.IGNCR: + s += ' IGNCR' + if attr & termios.IXON: + s += ' IXON' + if attr & termios.IXOFF: + s += ' IXOFF' + if attr & termios.IXANY: + s += ' IXANY' + if attr & termios.IMAXBEL: + s += ' IMAXBEL' + return s + + def _output(attr): + s = '' + if attr & termios.OPOST: + s += ' OPOST' + if attr & termios.ONLCR: + s += ' ONLCR' + if attr & termios.OCRNL: + s += ' OCRNL' + if attr & termios.TABDLY: + s += ' TABDLY' + if attr & termios.TAB0: + s += ' TAB0' + if attr & termios.TAB3: + s += ' TAB3' + if attr & termios.ONOCR: + s += ' ONOCR' + if attr & termios.ONLRET: + s += ' ONLRET' + return s + + def _control(attr): + s = '' + if (attr & termios.CSIZE) == termios.CS5: + s += ' CS5' + if (attr & termios.CSIZE) == termios.CS6: + s += ' CS6' + if (attr & termios.CSIZE) == termios.CS7: + s += ' CS7' + if (attr & termios.CSIZE) == termios.CS8: + s += ' CS8' + if attr & termios.CSTOPB: + s += ' CSTOPB' + if attr & termios.CREAD: + s += ' CREAD' + if attr & termios.PARENB: + s += ' PARENB' + if attr & termios.PARODD: + s += ' PARODD' + if attr & termios.HUPCL: + s += ' HUPCL' + if attr & termios.CLOCAL: + s += ' CLOCAL' + if attr & termios.CRTSCTS: + s += ' CRTSCTS' + return s + + def _local(attr): + s = '' + if attr & termios.ECHOKE: + s += ' ECHOKE' + if attr & termios.ECHOE: + s += ' ECHOE' + if attr & termios.ECHO: + s += ' ECHO' + if attr & termios.ECHONL: + s += ' ECHONL' + if attr & termios.ECHOPRT: + s += ' ECHOPRT' + if attr & termios.ECHOCTL: + s += ' ECHOCTL' + if attr & termios.ISIG: + s += ' ISIG' + if attr & termios.ICANON: + s += ' ICANON' + if attr & termios.IEXTEN: + s += ' IEXTEN' + if attr & termios.TOSTOP: + s += ' TOSTOP' + if attr & termios.FLUSHO: + s += ' FLUSHO' + if attr & termios.PENDIN: + s += ' PENDIN' + if attr & termios.NOFLSH: + s += ' NOFLSH' + return s + + def _baudrate(attr): + if attr == termios.B0: + s = 'B0' + elif attr == termios.B50: + s = 'B50' + elif attr == termios.B75: + s = 'B75' + elif attr == termios.B110: + s = 'B110' + elif attr == termios.B134: + s = 'B134' + elif attr == termios.B150: + s = 'B150' + elif attr == termios.B200: + s = 'B200' + elif attr == termios.B300: + s = 'B300' + elif attr == termios.B600: + s = 'B600' + elif attr == termios.B1800: + s = 'B1800' + elif attr == termios.B1200: + s = 'B1200' + elif attr == termios.B2400: + s = 'B2400' + elif attr == termios.B4800: + s = 'B4800' + elif attr == termios.B9600: + s = 'B9600' + elif attr == termios.B19200: + s = 'B19200' + elif attr == termios.B38400: + s = 'B38400' + elif attr == termios.B57600: + s = 'B57600' + elif attr == termios.B115200: + s = 'B115200' + elif attr == termios.B230400: + s = 'B230400' + elif attr == termios.B460800: + s = 'B460800' + else: + s = 'unknown' + return s + + if self.attr is None: + return 'None' + s = 'iflag: %s' % (_input(self.attr[0])) + s += os.linesep + 'oflag: %s' % (_output(self.attr[1])) + s += os.linesep + 'cflag: %s' % (_control(self.attr[2])) + s += os.linesep + 'lflag: %s' % (_local(self.attr[3])) + s += os.linesep + 'ispeed: %s' % (_baudrate(self.attr[4])) + s += os.linesep + 'ospeed: %s' % (_baudrate(self.attr[5])) + return s + + def _update(self): + self.off() + try: + termios.tcflush(self.fd, termios.TCIOFLUSH) + #attr = self.attr + #attr[0] = termios.IGNPAR; + #attr[1] = 0 + #attr[2] = termios.CRTSCTS | termios.CS8 | termios.CREAD; + #attr[3] = 0 + #attr[6][termios.VMIN] = 1 + #attr[6][termios.VTIME] = 2 + #termios.tcsetattr(self.fd, termios.TCSANOW, attr) + termios.tcsetattr(self.fd, termios.TCSANOW, self.attr) + termios.tcflush(self.fd, termios.TCIOFLUSH) + except: + raise + if self.is_on: + self.on() + + def _baudrate_mask(self, flag): + if flag == 'B0': + mask = termios.B0 + self.attr[5] = termios.B0 + elif flag == 'B50': + mask = termios.B50 + elif flag == 'B75': + mask = termios.B75 + elif flag == 'B110': + mask = termios.B110 + elif flag == 'B134': + mask = termios.B134 + elif flag == 'B150': + mask = termios.B150 + elif flag == 'B200': + mask = termios.B200 + elif flag == 'B300': + mask = termios.B300 + elif flag == 'B600': + mask = termios.B600 + elif flag == 'B1800': + mask = termios.B1800 + elif flag == 'B1200': + mask = termios.B1200 + elif flag == 'B2400': + mask = termios.B2400 + elif flag == 'B4800': + mask = termios.B4800 + elif flag == 'B9600': + mask = termios.B9600 + elif flag == 'B19200': + mask = termios.B19200 + elif flag == 'B38400': + mask = termios.B38400 + elif flag == 'B57600': + mask = termios.B57600 + elif flag == 'B115200': + mask = termios.B115200 + elif flag == 'B230400': + mask = termios.B230400 + elif flag == 'B460800': + mask = termios.B460800 + else: + mask = None + return mask + + def _input_mask(self, flag): + if flag == 'IGNBRK': + mask = termios.IGNBRK + elif flag == 'BRKINT': + mask = termios.BRKINT + elif flag == 'IGNPAR': + mask = termios.IGNPAR + elif flag == 'PARMRK': + mask = termios.PARMRK + elif flag == 'INPCK': + mask = termios.INPCK + elif flag == 'ISTRIP': + mask = termios.ISTRIP + elif flag == 'INLCR': + mask = termios.INLCR + elif flag == 'IGNCR': + mask = termios.IGNCR + elif flag == 'IXON': + mask = termios.IXON + elif flag == 'IXOFF': + mask = termios.IXOFF + elif flag == 'IXANY': + mask = termios.IXANY + elif flag == 'IMAXBEL': + mask = termios.IMAXBEL + else: + mask = None + return mask + + def _output_mask(self, flag): + if flag == 'OPOST': + mask = termios.OPOST + elif flag == 'ONLCR': + mask = termios.ONLCR + elif flag == 'OCRNL': + mask = termios.OCRNL + elif flag == 'TABDLY': + mask = termios.TABDLY + elif flag == 'TAB0': + mask = termios.TAB0 + elif flag == 'TAB3': + mask = termios.TAB3 + elif flag == 'ONOCR': + mask = termios.ONOCR + elif flag == 'ONLRET': + mask = termios.ONLRET + else: + mask = None + return mask + + def _control_mask(self, flag): + if flag == 'CSTOPB': + mask = termios.CSTOPB + elif flag == 'CREAD': + mask = termios.CREAD + elif flag == 'PARENB': + mask = termios.PARENB + elif flag == 'PARODD': + mask = termios.PARODD + elif flag == 'HUPCL': + mask = termios.HUPCL + elif flag == 'CLOCAL': + mask = termios.CLOCAL + elif flag == 'CRTSCTS': + mask = termios.CRTSCTS + else: + mask = None + return mask + + def _local_mask(self, flag): + if flag == 'ECHOKE': + mask = termios.ECHOKE + elif flag == 'ECHOE': + mask = termios.ECHOE + elif flag == 'ECHO': + mask = termios.ECHO + elif flag == 'ECHONL': + mask = termios.ECHONL + elif flag == 'ECHOPRT': + mask = termios.ECHOPRT + elif flag == 'ECHOCTL': + mask = termios.ECHOCTL + elif flag == 'ISIG': + mask = termios.ISIG + elif flag == 'ICANON': + mask = termios.ICANON + elif flag == 'IEXTEN': + mask = termios.IEXTEN + elif flag == 'TOSTOP': + mask = termios.TOSTOP + elif flag == 'FLUSHO': + mask = termios.FLUSHO + elif flag == 'PENDIN': + mask = termios.PENDIN + elif flag == 'NOFLSH': + mask = termios.NOFLSH + else: + mask = None + return mask + + def _set(self, index, mask, state): + if state: + self.attr[index] = self.attr[index] | mask + else: + self.attr[index] = self.attr[index] & ~mask + + def off(self): + if self.fd: + try: + termios.tcflow(self.fd, termios.TCOOFF) + except: + pass + try: + termios.tcflow(self.fd, termios.TCIOFF) + except: + pass + self.is_on = False + + def on(self): + if self.fd: + try: + termios.tcflow(self.fd, termios.TCOON) + except: + pass + try: + termios.tcflow(self.fd, termios.TCION) + except: + pass + self.is_on = True + + def baudrate(self, flag): + mask = self._baudrate_mask(flag) + if mask: + self.attr[4] = mask + self.attr[5] = mask + else: + raise error.general('invalid setting: %s' % (flag)) + self._update() + + def input(self, flag, on): + mask = self._input_mask(flag) + if mask is None: + raise error.general('invalid input flag: %s' % (flag)) + self._set(0, mask, on) + self._update() + + def output(self, flag, on): + mask = self._output_mask(flag) + if mask is None: + raise error.general('invalid output flag: %s' % (flag)) + self._set(1, mask, on) + self._update() + + def control(self, flag, on): + mask = self._control_mask(flag) + if mask is None: + raise error.general('invalid control flag: %s' % (flag)) + self._set(2, mask, on) + self._update() + + def local(self, flag, on): + mask = self._local_mask(flag) + if mask is None: + raise error.general('invalid local flag: %s' % (flag)) + self._set(3, mask, on) + self._update() + + def vmin(self, _vmin): + self.attr[6][termios.VMIN] = _vmin + + def vtime(self, _vtime): + self.attr[6][termios.VTIME] = _vtime + + def set(self, flags): + for f in flags.split(','): + if len(f) < 2: + raise error.general('invalid flag: %s' % (f)) + if f[0] == '~': + on = False + flag = f[1:] + else: + on = True + flag = f + if f.startswith('VMIN'): + vs = f.split('=') + if len(vs) != 2: + raise error.general('invalid vmin flag: %s' % (f)) + try: + _vmin = int(vs[1]) + except: + raise error.general('invalid vmin flag: %s' % (f)) + self.vmin(_vmin) + continue + if f.startswith('VTIME'): + vs = f.split('=') + if len(vs) != 2: + raise error.general('invalid vtime flag: %s' % (f)) + try: + _vtime = int(vs[1]) + except: + raise error.general('invalid vtime flag: %s' % (f)) + self.vtime(_vtime) + continue + mask = self._baudrate_mask(flag) + if mask: + if not on: + raise error.general('baudrates are not flags: %s' % (f)) + self.attr[4] = mask + self.attr[5] = mask + continue + mask = self._input_mask(flag) + if mask: + self._set(0, mask, on) + continue + mask = self._output_mask(flag) + if mask: + self._set(1, mask, on) + continue + mask = self._control_mask(flag) + if mask: + self._set(2, mask, on) + continue + mask = self._local_mask(flag) + if mask: + self._set(3, mask, on) + continue + raise error.general('unknown tty flag: %s' % (f)) + self._update() + +if __name__ == "__main__": + if len(sys.argv) == 2: + t = tty(sys.argv[1]) + t.baudrate('B115200') + t.input('BRKINT', False) + t.input('IGNBRK', True) + t.input('IGNCR', True) + t.local('ICANON', False) + t.local('ISIG', False) + t.local('IEXTEN', False) + t.local('ECHO', False) + t.control('CLOCAL', True) + t.control('CRTSCTS', False) + t.vmin(1) + t.vtime(2) + print t + t.set('B115200,~BRKINT,IGNBRK,IGNCR,~ICANON,~ISIG,~IEXTEN,~ECHO,CLOCAL,~CRTSCTS') + print t + t.on() + while True: + c = t.fd.read(1) + sys.stdout.write(c) |