You should be able to detect parity errors with the right termios settings, and even count them, depending on what the driver provides. The ioctl TIOCGICOUNT
(see man 4 tty_ioctl) can retrieve error counters, though this is not documented in the man page. The ioctl is not provided by Python, but the following script getcounts.py
does it through a low-level fcntl call that may need modifying for your system. It uses the structure described in the kernel serial.h
include file. (Note, the counters for real serial devices can also be seen in /proc/tty/driver/serial
, but not for usb devices).
#!/usr/bin/python2
# https://unix.stackexchange.com/a/525261/119298
import sys, fcntl, array
# ioctl to get counters. see /usr/include/linux/serial.h
# struct serial_icounter_struct{
# int cts, dsr, rng, dcd, rx, tx, frame, overrun, parity, brk,
# buf_overrun, reserved[9]; }
def getcounts(filename):
TIOCGICOUNT = 0x545D
fd = open(filename)
s = array.array('I',[0 for i in range(20)])
rc = fcntl.ioctl(fd.fileno(),TIOCGICOUNT,s,True)
if rc!=0:
print "rc",rc
names = "cts,dsr,rng,dcd,rx,tx,frame,overrun,parity,brk,bufo"
cts,dsr,rng,dcd,rx,tx,frame,overrun,parity,brk,bufo = s[:11]
for i,name in enumerate(names.split(",")):
print name,s[i]
fd.close()
getcounts(sys.argv[1])
For example, with 2 real serial ports connected via a crossover cable the following script will show 3 different results as we change the parity detection settings. Start off by setting both serial devices the same, to generate and detect even parity (-ignpar
with -
for "not"). The try
function is run 3 times to write hello
on ttyS1
, then to use xxd
to read the result from ttyS0
, and finally run getcounts.py
to print the counters:
#!/bin/bash
try()(
xxd -l 16 /dev/ttyS0 &
sleep 1
for i in 1 2 3 ; do echo hello; done >/dev/ttyS1
sleep 1
getcounts.py /dev/ttyS0
)
stty -F /dev/ttyS0 9600 raw -echo clocal
stty -F /dev/ttyS1 9600 raw -echo clocal
stty -F /dev/ttyS0 parenb -ignpar inpck parodd
stty -F /dev/ttyS1 parenb -ignpar inpck parodd
try # should be ok
stty -F /dev/ttyS0 -parodd
try # should get parity errors, lots of null data
stty -F /dev/ttyS0 parmrk
try # should get parity errors, lots of ff 00 prefix to each data
The first try should show us the data coming through ok, and a parity count of 0 (assuming we have just started using these devices):
00000000: 6865 6c6c 6f0a 6865 6c6c 6f0a 6865 6c6c hello.hello.hell
...
parity 0
...
Before the next try, we change to even parity on ttyS0
and we get the output
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
parity 16
i.e. a null char for each character with bad parity. The actual count of parity errors is 16 as xxd
stops after reading 16 characters.
Before the final try, we ask to mark the parity errors in the data. This makes the kernel put 2 bytes 0xff and 0x00 in front of each bad data character, and we get:
00000000: ff00 68ff 0065 ff00 6cff 006c ff00 6fff ..h..e..l..l..o.
parity 22
The parity count only goes up by 6 as xxd
terminates even earlier.
The data seen above should be the same for a usb driver, but you might not get any change in the counters.