CH341 driver USB adapter Serial port or QSerialPort not working on Linux

The following code works correctly for me on Windows, but Linux does not work. I use the same computer, both operating systems are installed on my own. I do not use a virtual machine. I need to work on Linux. I tried on different Linux distributions and haven’t worked anywhere.

// In the main class: QSerialPortInfo info = XXXX; // Generally in Linux: /dev/ttyUSB0, in win: COM1 QSerialPort serial; QObject::connect(&serial, SIGNAL(readyRead()), this, SLOT(onReadyRead()), Qt::DirectConnection); QObject::connect(&serial, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)), Qt::DirectConnection); QObject::connect(&serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onError(QSerialPort::SerialPortError)), Qt::DirectConnection); // Slot void MyClass::onReadyRead() { qDebug()<<"Signal onReadyRead"; buffer_mutex.lock(); buffer += serial.readAll(); qDebug()<<"Read: "<<qstr_to_hexstr(buffer); bufferNotEmpty.wakeAll(); buffer_mutex.unlock(); } void MyClass::onError(QSerialPort::SerialPortError error) { qCritical()<<"Serial Port Error: "<<(int)error; } void MyClass::onBytesWritten(qint64 size){ qDebug()<<"onBytesWritten: "<<size; } // In another place I did: serial.setPort(info); if(!serial.open(QIODevice::ReadWrite)) return false; qDebug()<<"Init Setting!..."; if(!serial.setBaudRate(QSerialPort::Baud9600)) qCritical()<<"Error in setBaudRate"; if(!serial.setDataBits(QSerialPort::Data8)) qCritical()<<"Error in setDataBits"; if(!serial.setParity(QSerialPort::EvenParity)) qCritical()<<"Error in setParity"; if(!serial.setStopBits(QSerialPort::OneStop)) qCritical()<<"Error in setStopBits"; if(!serial.setFlowControl(QSerialPort::SoftwareControl)) qCritical()<<"Error in setFlowControl"; if(!serial.setDataTerminalReady(true)) qCritical()<<"Error in setDataTerminalReady"; qDebug()<<"Setting ready!..."; 

When sending 1 byte, the device responds and sends the data correctly.

Example:

 // In the main class: const char enq[2] = {0x05, '\0'}; serial.write (enq); // In onReadyRead: serial.readAll(); // Works on Win / Linux 

If more than 1 byte device is sent, it does not respond to the request in Linux.

Example:

 // In the main class: const char command[6] = {0x02, 'S', '1', 0x03, 'a', '\0'}; serial.write(command); // In onReadyRead serial.readAll(); // Works only in Win 

This event is fired only in windows. On linux, it never works, is not received or arrives in a bad format, and never recognizes a remote device.

My log on windows:

 {Debug} Init Setting!... {Debug} Setting ready!... {Debug} Write: " 0x05 " {Debug} onBytesWritten: 1 {Debug} buffer wait!... {Debug} Signal onReadyRead {Debug} Read: " 0x02 `@ 0x03 #" {Debug} buffer size: 5 {Critical} Serial Port Error: 0 {Debug} Write: " 0x02 S1 0x03 a" {Debug} onBytesWritten: 5 {Debug} buffer wait!... {Debug} Signal onReadyRead {Debug} Read: " 0x02 S100 0x0A 00000000000000000 0x0A 00000479" {Debug} buffer size: 32 {Debug} buffer wait!... {Debug} Signal onReadyRead {Debug} Read: " 0x02 S100 0x0A 00000000000000000 0x0A 00000479 0x0A 00000 0x0A 00000330 0x0A 00000 0x0A 0061 0x0A 0000 0x0A " {Debug} buffer size: 64 {Debug} Signal onReadyRead {Debug} buffer wait!... {Debug} Read: " 0x02 S100 0x0A 00000000000000000 0x0A 00000479 0x0A 00000 0x0A 00000330 0x0A 00000 0x0A 0061 0x0A 0000 0x0A X-XXXXXXXX 0x0A XXXXXXXXX 0x0A 221715 0x0A 120414 0x0A 0x03 0x1B " {Debug} buffer size: 103 {Critical} Serial Port Error: 0 

(I replace the actual response of the device with the characters β€œX”)

My log on Linux:

 {Debug} Init Setting!... {Debug} Setting ready!... {Debug} Write: " 0x05 " {Debug} onBytesWritten: 1 {Debug} buffer wait!... {Debug} Signal onReadyRead {Debug} Read: " 0x02 `@ 0x03 #" {Debug} buffer size: 5 {Critical} Serial Port Error: 0 {Debug} Write: " 0x02 S1 0x03 a" {Debug} onBytesWritten: 5 {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} buffer wait!... {Debug} timeout!... (15 sec for timeout) 

USB Serial Adapter: CH340

 In Windows: USB\VID_1A86&PID_7523&REV_0254 In Linux: Apr 13 01:16:58 kali kernel: [47844.260136] usb 2-1: new full-speed USB device number 16 using uhci_hcd Apr 13 01:16:58 kali kernel: [47844.428098] usb 2-1: New USB device found, idVendor=1a86, idProduct=7523 Apr 13 01:16:58 kali kernel: [47844.428115] usb 2-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0 Apr 13 01:16:58 kali kernel: [47844.428126] usb 2-1: Product: USB2.0-Ser! Apr 13 01:16:58 kali kernel: [47844.431268] ch341 2-1:1.0: ch341-uart converter detected Apr 13 01:16:58 kali kernel: [47844.445398] usb 2-1: ch341-uart converter now attached to ttyUSB0 Apr 13 01:16:58 kali mtp-probe: checking bus 2, device 16: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1" Apr 13 01:16:58 kali mtp-probe: bus: 2, device: 16 was not an MTP device 

PD: Sorry for my English, try to do your best with Google Translator: (...

Additional Information 1:

 Apr 13 04:10:55 kali kernel: [ 4872.627980] tty ttyUSB0: serial_write - 1 byte(s) Apr 13 04:10:55 kali kernel: [ 4872.629763] tty ttyUSB0: serial_chars_in_buffer Apr 13 04:10:55 kali kernel: [ 4872.629778] tty ttyUSB0: serial_wait_until_sent Apr 13 04:10:55 kali kernel: [ 4872.638252] tty ttyUSB0: serial_chars_in_buffer Apr 13 04:10:55 kali kernel: [ 4872.638267] tty ttyUSB0: serial_write_room Apr 13 04:10:55 kali kernel: [ 4872.638278] tty ttyUSB0: serial_chars_in_buffer Apr 13 04:10:55 kali kernel: [ 4872.638287] tty ttyUSB0: serial_write_room Apr 13 04:10:55 kali kernel: [ 4872.639438] tty ttyUSB0: serial_chars_in_buffer Apr 13 04:10:55 kali kernel: [ 4872.639458] tty ttyUSB0: serial_write_room Apr 13 04:10:55 kali kernel: [ 4872.639475] tty ttyUSB0: serial_chars_in_buffer Apr 13 04:10:55 kali kernel: [ 4872.639488] tty ttyUSB0: serial_write_room Apr 13 04:10:56 kali kernel: [ 4873.641799] tty ttyUSB0: serial_ioctl - cmd 0x540b Apr 13 04:10:56 kali kernel: [ 4873.646884] tty ttyUSB0: serial_write - 5 byte(s) Apr 13 04:10:56 kali kernel: [ 4873.647152] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change Apr 13 04:10:56 kali kernel: [ 4873.647176] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01 Apr 13 04:10:56 kali kernel: [ 4873.647384] tty ttyUSB0: serial_chars_in_buffer Apr 13 04:10:56 kali kernel: [ 4873.647401] tty ttyUSB0: serial_wait_until_sent Apr 13 04:10:56 kali kernel: [ 4873.649144] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change Apr 13 04:10:56 kali kernel: [ 4873.649166] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01 Apr 13 04:10:56 kali kernel: [ 4873.692152] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change Apr 13 04:10:56 kali kernel: [ 4873.692170] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01 Apr 13 04:10:56 kali kernel: [ 4873.694133] ch341-uart ttyUSB0: ch341_update_line_status - multiple status change Apr 13 04:10:56 kali kernel: [ 4873.694148] ch341-uart ttyUSB0: ch341_update_line_status - delta=0x01 

I will rebuild ch341.c and add:

 if (!delta) return; dev_info(&port->dev, "%s - delta=0x%02X\n", __func__, delta); // <---- New Line if (delta & CH341_BIT_CTS) port->icount.cts++; if (delta & CH341_BIT_DSR) port->icount.dsr++; if (delta & CH341_BIT_RI) port->icount.rng++; if (delta & CH341_BIT_DCD) { port->icount.dcd++; tty = tty_port_tty_get(&port->port); if (tty) { usb_serial_handle_dcd_change(port, tty, status & CH341_BIT_DCD); tty_kref_put(tty); } } 

delta = 0x01 in the log - flag:

 #define CH341_BIT_CTS 0x01 

Additional Information 2:

In the write / read stream, I hope for wakeAll by working onReadyRead. If you pass the second, do a readAll before checking to see if the buffer is empty. Example:

 // In the main class: QWaitCondition bufferNotEmpty; // In my function write/read: serial.write(data, size); buffer_mutex.lock(); while(time(NULL)-timeStart<timeoutWait && serial.isOpen()) { buffer += serial.readAll(); if(buffer.count()>0){ qDebug()<<"buffer size: "<<buffer.count(); //Interprete the buffer here... if(bufferComplete) break; } qDebug()<<"buffer wait!..."; bufferNotEmpty.wait(&buffer_mutex, 1000); } buffer.clear(); buffer_mutex.unlock(); 

Additional Information 3:

My Kernel is 3.12.6, but I updated this file from GitHub to rebuild the following drivers:

https://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.c https://github.com/torvalds/linux/blob/master/drivers/usb/serial/usb-serial .c (commit d9a38a8741fdffabc32e6d0943b1cdcf22712bec)

+6
source share
1 answer

Thanks to the Linux developers, it solved my problem, the CH34x driver did not implement parity in maillist - this is the PATCH link for those who have this problem in the future, and whether they are applicable to the official kernel, so far only the path restores the driver.

http://marc.info/?l=linux-serial&m=139749273432052&w=2

+7
source

All Articles