Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QSerialPort::UnsupportedOperationError ("Invalid argument") error in opening /dev/diag port in Android device using QSerialPort in Qt Android



  • I want to build an android application with Qt which just opens the /dev/diag port in my Android device. At first, I have written a simple codes as follows:

    main.cpp

    #include <QCoreApplication>
    #include <QDebug>
    
    #include "serialporthandler.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        SerialPortHandler* serialPortHandler = new SerialPortHandler("/dev/diag");
        serialPortHandler->openSerialPort();
        return a.exec();
    }
    

    serialporthandler.h

    #ifndef MYSERIALPORT_H
    #define MYSERIALPORT_H
    
    #include <QDebug>
    #include <QFile>
    #include <QObject>
    #include <QtSerialPort/QSerialPort>
    #include <QtSerialPort/QSerialPortInfo>
    
    class SerialPortHandler : public QObject
    {
        Q_OBJECT
    public:
        SerialPortHandler(QString serialPort, QObject *parent = nullptr);
        ~SerialPortHandler();
        bool openSerialPort();
    
    private:
        QSerialPort* serial_;
        QString serialPort_;
    
    };
    
    #endif // MYSERIALPORT_H
    

    serialporthandler.cpp

    #include "serialporthandler.h"
    
    SerialPortHandler::SerialPortHandler(QString serialPort, QObject *parent)
    {
        serial_ = new QSerialPort(parent);
        serial_->close();
        serialPort_=serialPort;
    }
    
    SerialPortHandler::~SerialPortHandler()
    {
        serial_->reset();
        serial_->close();
        delete serial_;
    }
    
    bool SerialPortHandler::openSerialPort()
    {
        serial_->setPortName(serialPort_);
        serial_->setBaudRate(QSerialPort::Baud19200);
        serial_->setDataBits(QSerialPort::Data8);
        serial_->setParity(QSerialPort::NoParity);
        serial_->setStopBits(QSerialPort::OneStop);
        serial_->setFlowControl(QSerialPort::NoFlowControl);
    
        if (!serial_->open(QIODevice::ReadWrite))
        {
            qDebug()<<"ERROR: "<<serial_->error()<<serial_->errorString();
            return 0;
        }
        return 1;
    
    }
    

    After building and running this app on my Android device, the following error appeared:

    ERROR: QSerialPort::PermissionError "Permission denied"
    

    It means that my application has no permission to open /dev/diag port. So, in Ubuntu I opened adb shell and executed the following commands to change the permission:

    adb shell
    su
    setenforce 0
    chmod 777 /dev/diag
    

    Now, After executing the above commands and building my application again, I see this error and I don't know how can I solve that:

    ERROR: QSerialPort::UnsupportedOperationError "Invalid argument"
    

    (I am using java-8-openjdk-amd64, SDK Version: 25.2.5, NDK Version: 20.0.5594570, Clang Qt 5.12.7 (android_armv7))

    Update:

    This C language code, can simply open /dev/diag port of Android device:

    //serialPort_=/dev/diag    
    open(serialPort_.toStdString().c_str(), O_RDWR | O_LARGEFILE | O_NONBLOCK);
    

    But QSerialPort::open function can not!


  • Qt Champions 2020

    1. QSP does not supported on Android (nobody even checked it, AFAIK) and even removed from the build.
    2. Does your open() work without of O_LARGEFILE flag?
    3. I suspect that QSerialPort::UnsupportedOperationError "Invalid argument" error related to the QSP configuring, but not to open(). Because by default QSP::open() opens and then configures the QSP (set baud rate, stop bits and etc). So, maybe '/dev/diag ' just does not support serial port specifig ioctl() flags.


  • Thanks,

    1. I can open the other ports on Android using QSerialPort like ttyHSL0 and ttyHSUSB0.
    2. QSerialPort::open() just get the open mode (i.e. ReadOnly, WriteOnly, ReadWrite) as input argument and I don't know how can I set O_LARGEFILE flag.
    3. Is there a way to set ioctl() flags in QSerialPort?

  • Qt Champions 2020

    1. I can open the other ports on Android using QSerialPort like ttyHSL0 and ttyHSUSB0.

    Because /dev/ttyHSL0 and /dev/ttyHSUSB0 is a 'true' serial ports... But, seems that /dev/diag is not a serial port.

    1. QSerialPort::open() just get the open mode (i.e. ReadOnly, WriteOnly, ReadWrite) as input argument and I don't know how can I set O_LARGEFILE flag.

    No, just test your native ::open() function (not QSP) just without of O_LARGEFILE flag and report us about results. If a problem is in O_LARGEFILE then it is not a problem to add it to QSP.

    1. Is there a way to set ioctl() flags in QSerialPort?

    What are flags? QSP already use ioctl's() calls (e.g. inside of QSP::open()), wrapped e.g. by tcsetattr() to change the termius structure, or some ioctl's() directly to change the speed and etc.

    You should re-build QSP for Android himself and debug it (or, at least to add qDebug() console outputs) to see, where it fails.

    UPD: I have found some info about /dev/diag. Seems, it is a special Qualcomm modem interface. So, most likelly, for this device don't inplemented some 'standard' serial port features (e.g. baud rate, stop bits and etc). You can look on a Kernel sources too to see where is the EINVAL errno returned.



  • I can open this port by:

    int fd=open("/dev/diag", O_RDWR);
    qDebug()<<"Open port with C function: "<<fd
    

    and the fd=33.
    There are just a few codes in QSP sources in github link

    Vtable for std::invalid_argument
    std::invalid_argument::_ZTVSt16invalid_argument: 5u entries
    0     (int (*)(...))0
    8     (int (*)(...))(& _ZTISt16invalid_argument)
    16    (int (*)(...))std::invalid_argument::~invalid_argument
    24    (int (*)(...))std::invalid_argument::~invalid_argument
    32    (int (*)(...))std::logic_error::what
    
    Class std::invalid_argument
       size=16 align=8
       base size=16 base align=8
    std::invalid_argument (0x0x7f3911e1a8f0) 0
        vptr=((& std::invalid_argument::_ZTVSt16invalid_argument) + 16u)
      std::logic_error (0x0x7f3911e1a958) 0
          primary-for std::invalid_argument (0x0x7f3911e1a8f0)
        std::exception (0x0x7f3911f4a2a0) 0 nearly-empty
            primary-for std::logic_error (0x0x7f3911e1a958)
    

    But I think the above source does not help!
    Yes, /dev/diag port is a special Qualcomm mobile and modem interface. I prefer to not to use C functions. Before building the QSP sources to debug, is there another way to open this special interface using Qt? (C can simply open it but Qt?!)


  • Qt Champions 2020

    I can open this port by:

    So, as I said, the problem is not in O_LARGEFILE.

    There are just a few codes in QSP sources in github link

    This is not a sources, the sources is in.