2014-04-13 17 views
6

Der folgende Code funktioniert für mich richtig in Windows, aber Linux funktioniert nicht. Ich benutze den gleichen PC, beide Betriebssysteme sind nativ installiert. Ich benutze keine virtuelle Maschine. Ich muss unter Linux arbeiten. Ich habe es in verschiedenen Linux-Distributionen versucht und funktioniert nirgends.Treiber CH341 USB Adapter Serieller Port oder QSerialPort funktioniert nicht in Linux

// 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!..."; 

Beim Senden von 1 Byte antwortet das Gerät und sendet die Daten korrekt.

Beispiel:

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

// In onReadyRead: 
serial.readAll(); // Works on Win/Linux 

Wenn ein mehr als 1 Byte-Gerät gesendet die Anforderung nicht in Linux antworten.

Beispiel:

// 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 

Dieses Ereignis ausgelöst wird, nur in den Fenstern. In Linux funktioniert es nie, nicht empfangen oder kommt in schlechtem Format an und hat das entfernte Gerät nie erkannt.

Mein Protokoll 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 

(ich die tatsächliche Reaktion des Gerätes durch die 'X'-Zeichen ersetzen)

Mein 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) 

Serielle USB 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 für mein Englisch, versuchen, mein Bestes mit Google Translator zu tun: (...

Weitere Informationen 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 ch341.c wieder aufzubauen und fügen:

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 der Protokoll-flag:

#define CH341_BIT_CTS 0x01 

Weitere Informationen 2:

Im Thread von schreiben/lesen ich hoffe auf wakeAll, läuft auf onReadyRead. Wenn Sie eine Sekunde überschreiten, machen Sie einen readAll, bevor Sie prüfen, ob der Puffer leer ist. Beispiel:

// 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(); 

Mehr Informationen 3:

Mein Kernel ist 3.12.6, aber ich aktualisierte von GitHub diese Datei neu erstellen diese Treiber:

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)

+0

Ich denke, es das gleiche Problem ist, dass Sie [hier] berichtet (https://bugreports.qt-project.org/browse/QTBUG-38305)? – lpapp

+0

Ja. Es kann ein Problem in QT oder Kernel sein. – Kijam

+0

Erste Fragen zuerst: Haben Sie versucht, die existenten Async-Befehlszeilen-Reader/Writer-Beispiele anzupassen? Arbeiten Sie? – lpapp

Antwort

7

Dank an die Entwickler von Linux, mein Problem gelöst, der CH34x Fahrer nicht Parität in der Mail-Liste implementiert ist der Link-PATCH für diejenigen, die dieses Problem in der Zukunft haben, nicht, ob sie für den offiziellen Kernel gelten, denn jetzt ist nur Weg den Treiber neu aufzubauen.

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

+2

Ich schätze deine Beharrlichkeit und dränge auf das Thema, also +1. :-) – lpapp