Reading from character device with Qt

Viewed 580

I'm not very good at character devices, so I need your help. A have a char device(let's call it /dev/my_light) which is a light sensor. I have to read the data from this file and transform it to the brightness value and then pass it to the brightness manager that changes the brightness of my screen. The problem is that when I read the value for some period of time I get old values from the file.I assume there is a buffer(again not sure how character devices exactly work). Whereas when I use cat /dev/my_light I see new data! Is it possible to get rid off the buffer and read new values that were written to the file just right now. Here is my code in Qt:

    void MySensor::updateMySensor()
    {
        Packet packet;
        packet.startByte = 0;
        packet.mantissa = 0;
        packet.exp = 0;

        d->device = ::open(d->path.toStdString().c_str(), O_RDONLY);
        if (d->device == -1)
        {
            qDebug() << Q_FUNC_INFO << "can't open the sensor";
            return;
        }

        ssize_t size = ::read(d->device, &packet, sizeof(packet));
        close(d->device);

        if (size == -1)
        {
            qDebug() << errno;
            return;
        }

        packet.exp &= 0x0F;

        float illumination = pow(2, packet.exp) * packet.mantissa * 0.045;

        if(d->singleShot) emit lightSensorIsRunning(true);
        emit illuminationRead(illumination);
    }

The mySensor function is called every second. I tried to call it each 200 msec but it didn't help. The value of illumination stays old for about 7 seconds(!) whereas the value that I get from cat is new just immediately.

Thank you in advance!

1 Answers

I can't test with your specific device, however, I'm using the keyboard as a read only device.

The program attempts to connect to keyboard and read all keys pressed inside and outside the window. It's a broad solution you'll have to adapt to meet your demands.

Note that I'm opening the file with O_RDONLY | O_NONBLOCK which means open in read only mode and no wait for the event be triggered(some notifier needed to know when data is ready!) respectively.

You'll need super user privilege to run this example!

#include <QtCore>
#include <fcntl.h>
#include <linux/input.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    const char *device_name = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";

    int descriptor = open(device_name, O_RDONLY | O_NONBLOCK);

    if (descriptor < 0)
    {
        qDebug() << "Error" << strerror(errno);
        return a.exec();
    }

    QFile device;

    if (!device.open(descriptor, QFile::ReadOnly))
    {
        qDebug() << "Error" << qPrintable(device.errorString());
        return a.exec();
    }

    QSocketNotifier notifier(device.handle(), QSocketNotifier::Read);

    QObject::connect(&notifier, &QSocketNotifier::activated, &notifier, [&](int socket){
        Q_UNUSED(socket)

        struct input_event ev;

        QByteArray data = device.readAll();

        qDebug() << "Event caught:"
                 << "\n\nDATA SIZE" << data.size()
                 << "\nSTRUCT COUNT" << data.size() / int(sizeof(input_event))
                 << "\nSTRUCT SIZE" << sizeof(input_event);

        qDebug() << ""; //New line

        while (data.size() >= int(sizeof(input_event)))
        {
            memcpy(&ev, data.data(), sizeof(input_event));

            data.remove(0, int(sizeof(input_event)));

            qDebug() << "TYPE" << ev.type << "CODE" << ev.code << "VALUE" << ev.value << "TIME" << ev.time.tv_sec;
        }

        qDebug() << ""; //New line
    });

    return a.exec();
}
Related