Driver Ch341 Usb Adapter Serial Port or Qserialport Not Works in Linux

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



Leave a reply



Submit