La porta seriale dell'adattatore USB del driver CH341 o QSerialport non funziona in Linux
-
21-12-2019 - |
Domanda
Il seguente codice funziona correttamente in Windows, ma Linux non funziona. Sto usando lo stesso PC, entrambi i sistemi operativi sono installati nativi. Non uso la macchina virtuale. Ho bisogno di lavorare su Linux. Ho provato in diverse distribuzioni Linux e non funziona da nessuna parte.
// 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!...";
.
Se l'invio di 1 byte il dispositivo risponde e invia correttamente i dati.
Esempio:
// In the main class:
const char enq[2] = {0x05, '\0'};
serial.write (enq);
// In onReadyRead:
serial.readAll(); // Works on Win / Linux
.
Se inviato un dispositivo più di 1 byte non risponde alla richiesta in Linux.
Esempio:
// 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
.
Questo evento viene attivato solo in Windows. In Linux non funziona mai, non ricevuto o arriva in formato cattivo e non ha mai riconosciuto il dispositivo remoto.
My Log in 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
.
(Sostituisco la risposta effettiva del dispositivo da parte dei caratteri "X")
Il mio log in 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)
.
Adattatore seriale USB: 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: Scusa per il mio inglese, prova a fare del mio meglio con Google Translator: (...
Ulteriori informazioni 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 Riablizione CH341.C e aggiungi:
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 nel registro è flag:
#define CH341_BIT_CTS 0x01
.
Ulteriori informazioni 2:
Nel filo della scrittura / lettura spero che WakeAll, in esecuzione su onReadyRead. Se si passa un secondo, crea un readall prima del controllo se il buffer è vuoto. Esempio:
// 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();
.
Ulteriori informazioni 3:
Il mio kernel è 3.12.6, ma ho aggiornato da GitHub Questo file è ricostituire questi driver:
https://github.com/torvaldds/ Linux / Blob / Master / Driver / USB / Serial / CH341.c https://github.com/torvalds/linux /blob/master/drivers/usb/serial/usb-serial.c . (commettere D9A38A8741FDFFFABC32E6D0943B1CDCF22712BEC)
Soluzione
Grazie agli sviluppatori di Linux, ha risolto il mio problema, il Driver CH34x non implementato la parità nel Maillist è la patch di collegamento per coloro che hanno questo problema in futuro, non se si applicano al kernel ufficiale, per ora solo viaè ricostruire il driver.
http://marc.info/?l=linux-serial&amt;m=139749273432052 & w= 2