Sam Price 7dc34d2cab rtems-tools: stty rename / spelling bug.
This patch fixes a spelling/rename mistake in rtems-tools.
2023-09-11 14:11:48 -05:00

585 lines
18 KiB
Python

#
# 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 fcntl
import os
import sys
import termios
from rtemstoolkit import error
from rtemstoolkit import host
from rtemstoolkit import path
def save():
if not host.is_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(object):
raw = 'B115200,~BRKINT,IGNBRK,IGNCR,~ICANON,~ISIG,~IEXTEN,~ECHO,CLOCAL,~CRTSCTS'
def __init__(self, dev):
if host.is_windows:
raise error.general('termios not support on host')
self.dev = dev
self.default_attr = None
self.fd = None
self.if_on = False
if host.is_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 as 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:
close(self.fd)
raise error.general('cannot get termios attrs: %s' % (dev))
try:
fcntl.fcntl(self.fd, fcntl.F_SETFL,
fcntl.fcntl(self.fd, fcntl.F_GETFL) | os.O_NONBLOCK)
except:
close(self.fd)
raise error.general('cannot make tty non-blocking: %s' % (dev))
self.attr = self.default_attr
def __del__(self):
if self.fd and self.default_attr:
try:
fcntl.fcntl(self.fd, fcntl.F_SETFL,
fcntl.fcntl(self.fd, fcntl.F_GETFL) & ~os.O_NONBLOCK)
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 = None):
if flags is None:
flags = self.raw
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()
def read(self):
return self.fd.read()
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)