QtSerialPort does not detect parity error under linux
I have developed an application that uses Space and Mark parity configuration. It is an implementation of an old but still in force protocol. When a new frame starts, the first byte is with mark and others with space. So I change parity settings in runtime and I must be able to detect if the byte incoming through serial port has a mark or a space.
It works fine in windows, but I need it on linux so when I switched to Debian, it didnt work anymore. After debugging I was able to see that mySerialPort->error() never return anything related to parity error.
Anybody has experienced a similar behavior? Is there any bug? in QtSerialPort class?
Thank you to everybody.
To be honest, nobody checked it on Linux. :)
Probably that your device driver just do not suport this feature to detect a framing errors, or, maybe the qserialport has bugs.
Also, your serial port side should be opened without NoParity flag (e.g. with EvenParity, OddParity, or, maybe with MarkParity or SpaceParity), to able to detect any incoming frame errors.
Anyway, this "framing error detection" feature" is doubtful (and can be deprecated in future), because it depends on many reasons.. Besides, it reduces the stream performance, because it reads a byte by byte to able to trying to detect the framing errors.
If I understand correctly, you configure the serial port to expect Space (0) as the parity bit. When the remote sender puts its first byte on the wire it deliberately sends Mark (1) as the parity bit. You expect to see a parity error flagged (different to a framing error), indicating the "first byte", but also expect the "corrupt" byte to be passed on to your program.
It's possible (without looking) that the Linux serial port driver never announces the broken parity or passes on the "corrupt" byte, or that QSerialPort does the same. Does your program actually see the "corrupt" byte or is it completely absent?
I see that any form of buffering could play havoc with this scheme: you have a parity error and three buffered bytes to choose from for example.
Dear all. Just to clarify, I never said "framing error".
My app is always looking into serial port so there is no chance to have more than 1 byte in buffer. The first byte must be with a mark, if not, it is not the first byte of the message.
Under windows, it works fine and fast enough to comply with such a protocol (SAS).
- open serial port
- set Space Parity
- wait for a byte and read inmediatly after it arrives
- call sp->error() and look for QSerialPort::ParityError
- if there is a parityError, then I received a "Marked" byte because it was received with mark parity
- read the rest of bytes (with space Parity) that correspond to the rest of message.
I know when "marked" byte arrives because I can read it and also I see it on my osciloscope. The thing is I do not see QSerialPort::ParityError. Do you suggest that the fact of reading the byte first and THEN looking for a parity error could could be making the difference?
Thank you for your support. I hope it is not a Bug on QSerialPort but if it is, I will be proud of collaborating for the first time.
POSIX API uses the byte stuffing to detecting of a frame errors. You can debug QSerialPort guts, look on readPerChar() method.
I mean, you should himself do it, because nobody did not check it.
PS: I tried to do it earlier, but unsuccessfully, because I have not appropriate device with the "framing detection feature". Maybe that the chip do not support it, or can be that the driver do not suport it (e.g. on Windows it will be works, but on Linux - not... by the driver reasons).. So, need to check it manually on your side with your device.. :). Also you can look on the driver's source code.. :)
PSPS: What is chip vendor you are use (PL2303, FTDI)?
I have tried on the native Serial Port (COM1/ttyS0) on the same desktop machine I have installed Debian / Windows.
Also tryed through a couple of Serial Ports implemented with a PCI card (COM9/ttyS2 and COM 10/ttyS3). And also over a FTDI USB adapter (COMx / ttyUSB0).
Parity Error detection works fine on all situation using windows, but it doesnt work on any if using linux.
Ok.. then only you can help himself in this case... I have no yet the HW serial ports to check it on my side. sorry. :)
After working around.
I realize it is happening only in the Debian linux I have installed. I tryed with Ubuntu (Live CD) using minicom, putty and also cutecom and parity seems to work fine for native Serial Port as well as USB serial adapter.
I couldn't test QSerialPort yet, but I am pretty sure there is something wrong in my linux instance.
Thankyou very much to all of you. this forum has helped many times.
PD: If anybody has an idea of what is going on with my debian instalation, I will really appreciate that.
Thank you very much again.
I don't understand a bit, how do you detect a frame error using Putty?
After working a bit (few days indeed), it has been revealed.
QSerialPort is implemented under linux using termios.
The code for method
QSerialPort::setParity(QSerialPort::Parity parity)in qserialport_unix.cpp doesn't allow parity error detection. Please take a look in the first two lines of code:
currentTermios.c_iflag &= ~(PARMRK | INPCK);<- here INPCK is deliberately disabled
currentTermios.c_iflag |= IGNPAR;<- Ignore Parity errors.
Library should be modified in order to process input parity errors.
If I use in my application:
QSerialPort::setParity(QSerialPort::OddParity);and inmediatly after
QSerialPort::setParity(QSerialPort::UnknownParity);so switch/case/default of the method is executed and incoming parity errors are now detected! Then, error signal should be emited, and etc.
I would like to collaborate with this given I need it and maybe to help in improvements of Qt libraries. I dont know how to do that.
I hope it is clear, it wasn't easy to realize my self where were the problem.
@kuzulis I used putty just to send data to my app. As you suggest, putty doesn´t detect parity errors.