2

I have read the QIODevice doc, but still don't know how to archive that. What I want to do is to create a KeyBoard class deriving from QIODevice. which opens /dev/input/eventX. I hope that my code can use the readyRead() signal of KeyBoard. (QFile does not emit readyRead() signal)

class KeyBoard : public QIODevice {
public:
    KeyBoard();
    ~KeyBoard();
protected:
    qint64 readData(char *data, qint64 size);
    qint64 writeData(const char *data, qint64 size);
};

What do I need to do in readData() and writeData()? And how does my code use this class? (I just use the QCoreApplication, no gui)

Timothy Kwok
  • 301
  • 2
  • 9

1 Answers1

1

Use QSocketNotifier on the open file handle. You can read from the device using QFile,or abuse QSerialPort, i.e. QSerialPort m_port{"input/eventX"}. See this answer for an example of using QSocketNotifier with stdin; /dev/input/eventX requires a similar approach.

Here's an example that works on /dev/stdio, but would work identically on /dev/input/eventX.

// https://github.com/KubaO/stackoverflown/tree/master/questions/dev-notifier-49402735
#include <QtCore>
#include <fcntl.h>
#include <boost/optional.hpp>

class DeviceFile : public QFile {
   Q_OBJECT
   boost::optional<QSocketNotifier> m_notifier;
public:
   DeviceFile() {}
   DeviceFile(const QString &name) : QFile(name) {}
   DeviceFile(QObject * parent = {}) : QFile(parent) {}
   DeviceFile(const QString &name, QObject *parent) : QFile(name, parent) {}
   bool open(OpenMode flags) override {
      return
            QFile::isOpen()
            || QFile::open(flags)
            && fcntl(handle(), F_SETFL, O_NONBLOCK) != -1
            && (m_notifier.emplace(this->handle(), QSocketNotifier::Read, this), true)
            && m_notifier->isEnabled()
            && connect(&*m_notifier, &QSocketNotifier::activated, this, &QIODevice::readyRead)
            || (close(), false);
   }
   void close() override {
      m_notifier.reset();
      QFile::close();
   }
};

int main(int argc, char **argv) {
   QCoreApplication app{argc, argv};
   DeviceFile dev("/dev/stdin");
   QObject::connect(&dev, &QIODevice::readyRead, [&]{
      qDebug() << "*";
      if (dev.readAll().contains('q'))
         app.quit();
   });
   if (dev.open(QIODevice::ReadOnly))
      return app.exec();
}

#include "main.moc"
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313