用Qt读取字符设备

用Qt读取字符设备,qt,file,Qt,File,我不太擅长角色设计,所以我需要你的帮助。A有一个char设备,我们称之为/dev/my_light,它是一个光传感器。我必须从这个文件中读取数据,并将其转换为亮度值,然后将其传递给亮度管理器,以更改屏幕的亮度。问题是,当我读取一段时间的值时,我会从文件中获取旧值。我假设有一个缓冲区,但我不确定字符设备到底是如何工作的。然而,当我使用cat/dev/my_light时,我看到了新的数据!是否可以去掉缓冲区并读取刚刚写入文件的新值。以下是我在Qt中的代码: void MySensor::up

我不太擅长角色设计,所以我需要你的帮助。A有一个char设备,我们称之为/dev/my_light,它是一个光传感器。我必须从这个文件中读取数据,并将其转换为亮度值,然后将其传递给亮度管理器,以更改屏幕的亮度。问题是,当我读取一段时间的值时,我会从文件中获取旧值。我假设有一个缓冲区,但我不确定字符设备到底是如何工作的。然而,当我使用cat/dev/my_light时,我看到了新的数据!是否可以去掉缓冲区并读取刚刚写入文件的新值。以下是我在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);
    }
mySensor函数每秒调用一次。我试着每200毫秒调用一次,但没有用。照明值会保持7秒左右!然而,我从cat得到的值是新的


提前谢谢你

我无法使用您的特定设备进行测试,但是,我将键盘用作只读设备

程序尝试连接到键盘并读取窗口内外按下的所有键。这是一个广泛的解决方案,你必须适应以满足你的需求

请注意,我正在使用O|RDONLY | O|NONBLOCK打开文件,这意味着在只读模式下打开,无需等待事件触发。一些通知程序需要知道数据何时准备就绪!分别

您需要超级用户权限才能运行此示例

#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();
}

我们不确定该设备的具体细节,因此无法对答案充满信心。当然,如果设备上没有更新,您可能会从中获得相同的值。我们如何知道新数据可用?根据我过去的经验,一些设备会发出新数据的信号,我们可以使用POSIX select或epoll对它们进行监视。看起来有点像相关文章:@Alexandev thanxs为您解答!问题是,对于cat,我现在可以看到新的值。在我的程序中,我在7秒后看到它们,正如我上面所说的。我不明白为什么。也许我的问题不是很清楚,它起作用了!非常感谢。但为什么有必要同时使用O_非块O_NDELAY?它们是一样的……还是我错了?QSocketNotifier就是那个使用基础select或epoll的东西。@PolinaBodnar:没错,O_NDELAY是O_NONBLOCK的过时名称,不应该在新的应用程序中使用。我将从答案中删除它!