Driver CH341 USB Adapter Serial Port or QSerialPort not Works in Linux
Thanks to the developers of Linux, solved my problem, the CH34x driver not implemented parity in the maillist is the link PATCH for those who have this problem in the future, not whether they apply to the official kernel, for now only way is rebuild the driver.
http://marc.info/?l=linux-serial&m=139749273432052&w=2
Trouble in reading from Serial port using QSerialPort
You cannot (well, SHOULD not) write then read from a QSerialPort
in the same function.
There are two methods which I use for QSerialPort
processing:
METHOD ONE
Create and open your QSerialPort
object.
Set up a QTimer
with a timeout of around 50 ms or so (depends on hardware).
Connect the readyRead()
signal to a slot which basically just reads all data into your buffer (QByteArray
is ideal for this). The slot stops the QTimer
, reads all data available with readAll() and then restarts the QTimer
and returns.
Connect the timeout
signal of the QTimer
to a function to process the read bytes of input.
The premise here is that eventually all data will have arrived and the QTimer
will timeout, at which point you will have had all of your data in the buffer to process.
METHOD TWO
The slot which handles readyRead()
signal can check all data in the buffer for some "marker" which denotes that some chunk of data has fully arrived. Many devices use 0x0D
or 0x0d0x0A
as the delmiter. Others use NULL 0x00
or some other byte.
Evaluate the buffer at each iteration of the readyRead()
handler slot.
This example shows the second choice and it works well for small reads.
r_port = new QSerialPort(this);
r_port->setPortName("COM3");
r_port->setBaudRate(QSerialPort::Baud9600);
r_port->setDataBits(QSerialPort::Data8);
r_port->setParity(QSerialPort::NoParity);
r_port->setStopBits(QSerialPort::OneStop);
r_port->setFlowControl(QSerialPort::NoFlowControl);
if (r_port->open(QSerialPort::ReadWrite))
{
connect(r_port, &QSerialPort::readyRead, this, &MYPROG::on_readyRead);
connect(r_port, &QSerialPort::errorOccurred, this, &MYPROG::breakCaught);
}
else
{
QMessageBox::critical(this, "SERIAL PORT NOT CONNECTED", "Unable to connect to the radio.\n\nPlease check your connections\nand configuration and try again.");
return;
}
void MYPROG::on_readyRead()
{
// keep reading until we get a \r\n delimiter
rxBytes.append(r_port->readAll());
qDebug()<<"raw rxBtes"<<rxBytes;
if(!rxBytes.contains("\r\n"))
{
return;
}
int end = rxBytes.lastIndexOf("\r\n") + 2;
QStringList cmds = QString(rxBytes.mid(0, end)).split("\r\n", QString::SkipEmptyParts);
rxBytes = rxBytes.mid(end);
foreach(QString cmd, cmds){
qDebug()<<"serial read"<<cmd;
}
}
This allows the QSerialPort to be read when data arrives and then the program can return to the event loop in order to keep a GUI from becoming unresponsive. Typical serial reads are small and of short time duration so UI freezing rarely happens using these methods.
How to set low latency in serial port open by QSerialPort
The descriptor is the Handle of the QSerialPort:
#include <sys/ioctl.h>
#include <linux/serial.h>
// ...
pUsbSerialPort->open(QIODevice::ReadOnly);
int fd = pUsbSerialPort->handle();
struct serial_struct kernel_serial_settings;
::ioctl(fd, TIOCGSERIAL, &kernel_serial_settings);
kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
::ioctl(fd, TIOCSSERIAL, &kernel_serial_settings);
Read all input from QSerialPort
The answer to my problem is (partly) described in this question: External vs internal declaration of QByteArray. My problem (why I did not receive any further data) was that I did not send a \x00D
after the input line, thus the device just echoed my input, and was waiting for the Enter
afterwards. After the input looks exactly as the first line, I misunderstood it for just getting the first line, and nothing else.
Why container_of macro prevents other parts of the kernel from modifying the unique fields of your structure?
The webpage you linked to had the following example:
struct i2c_driver {
char name[32];
struct device_driver driver;
};
The Linux device driver core is only going to care about the struct device_driver
and not about the specifics related to struct i2c_driver
. This is the abstraction level that the device driver core cares about. Therefore in the Linux device driver core a pointer to a struct device_driver
is going to be passed around, not a pointer to a device specific struct. If you have a struct device_driver
you cannot determine without some other knowledge what type of struct contains the struct device_driver
.
To make an analogy using object oriented programming terminology: struct i2c_driver
is a child "class" of struct device_driver
. In object oriented programming you cannot go from a parent type (e.g. struct device_driver
) to a child type (e.g. struct i2c_driver
), without some other information, such as information gained by using a typeof
operating or something similar.
Similarly, if some piece of code has a pointer to a struct device_driver
unless it makes some assumption about what the pointer is pointing to, it will not try to access any of the struct i2c_driver
fields.
Note that "prevent" really isn't the word I would pick because at least in my opinion "prevent" imply that there is some compile-time or run-time protection that will stop this from happening. This is not the case. Instead well written code that adheres to the conventions set out with regards to abstraction of device drivers will not manipulate the "child" object fields. There is nothing that prevents someone from doing this however, beyond breaking the abstraction.
Finally, the sentence before the one you are referring to sheds some light on this:
The driver core only passes in the type of driver structure registered with it, so this type of manipulation is safe. This also prevents other parts of the kernel from modifying the unique fields of the structure used to control the subsystem's code.
Basically, reiterating that the driver core only cares about struct device_driver
not anything device specific.
Related Topics
Dos2Unix: Binary Symbol Found, Skipping Binary File
/Usr/Local/Ssl/Lib/Libcrypto.A: Could Not Read Symbols: Bad Value
Setting Environment Variable with Leading Digit in Bash
Dynamic Listening Ports Inside Docker Container
Bind Outgoing Traffic to Eth0 Instead of Eth0:1
How Linux Scheduler Schedules Processes on Multi-Core Processors
Convert Charset from a Entire Project to Utf-8
Upgrading PHPmyadmin (And Other Packages) on Debian Squeeze
Golang Os/Exec, Realtime Memory Usage
Linux Stand Alone Executable Generation
Oracle Instant Client: Ora-28759: Failure to Open File
"Hello World" Function Without Using C Printf
Get X/Y Position of Caret (Input Text Cursor) Under Xorg
Scale PDF to Add Border for Printing Full Size Pages
Different Utf-8 Signature for Same Diacritics (Umlauts) - 2 Binary Ways to Write Umlauts