从/dev/input/event0读取boost::asio

5

我希望使用boost::asio从12位数字键盘中读取数据。目前我可以在没有boost的情况下这样做:

fd = open ("/dev/input/event0", 0_NONBLOCK);
read (fd, &ev, sizeof ev);

你知道如何使用boost::asio实现这个吗?我正在使用Linux和c++。这篇帖子和这篇帖子很有用。我不会使用串口(io,“/dev/usb/hiddev0”),因为它不是串口,对吧?谢谢。

我可以打开设备,获取文件描述符,然后在asio中使用它。 - xinthose
2
Boost.Asio 提供了现代化的 C++ 接口,但在其实现中使用了纯 C(或 OS)函数。因此,首先值得理解为什么上述 read 不起作用。您观察到了什么行为? - Igor R.
1
高度相关:考虑使用库而不是直接访问原始设备:https://dev59.com/qYLba4cB1Zd3GeqPk-m4#25559167 - sehe
@IgorR。我无法通过这种方式打开设备:serial_port port (io, "/dev/usb/hiddev0"); 我认为我应该使用stream_descriptor。 - xinthose
1个回答

5

在我的系统中,event2 代表鼠标,在下面这个简单的 readloop 程序中表现得非常好。

以 root 身份运行:

#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/bind.hpp>

#include <iostream>      // for debug output
#include <iomanip>

#include <linux/input.h> // for input_event
#include <boost/range/adaptor/sliced.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

using namespace boost::asio;

struct input {
    using error_code = boost::system::error_code;
    using sliced = boost::adaptors::sliced;

    input(const char* devspec) : svc(), sd(svc, open(devspec, O_RDONLY)) {
        readloop(); // post work
    }

    void run() {
        svc.run();
    }

  private:
    io_service svc;
    posix::stream_descriptor sd;

    std::vector<input_event> events;

    void handle_input(error_code ec, size_t bytes_transferred) {
        if (!ec) {
            auto const n = bytes_transferred / sizeof(input_event);

            for (auto& ev : events | sliced(0,n)) {
                using namespace boost::posix_time;

                ptime ts({1970,1,1}, seconds(ev.time.tv_sec) + microsec(ev.time.tv_usec));

                std::cout << std::dec << ts.time_of_day() << "\t" << std::hex 
                          << std::hex << ev.type << " " << ev.code  << " " << ev.value << "\n";
            }

            std::cout << "\n";

            readloop();
        } else {
            std::cerr << ec.message() << "\n";
        }
    }

    void readloop() {
        events.resize(32);
        sd.async_read_some(buffer(events), boost::bind(&input::handle_input, this, placeholders::error, placeholders::bytes_transferred));
    }

};

int main()
{
    input monitor("/dev/input/event2");
    monitor.run();
}

典型输出:

22:33:09.705346 2 0 ffffffff
22:33:09.705346 2 1 1
22:33:09.705346 0 0 0

22:33:09.713412 2 0 ffffffff
22:33:09.713412 2 1 1
22:33:09.713412 0 0 0

22:33:09.721308 2 0 ffffffff
22:33:09.721308 0 0 0

22:33:09.729328 2 0 ffffffff
22:33:09.729328 0 0 0

22:33:09.737346 2 1 1
22:33:09.737346 0 0 0

22:33:09.745328 2 0 ffffffff
22:33:09.745328 2 1 1
22:33:09.745328 0 0 0

22:33:11.897301 4 4 90001
22:33:11.897301 1 110 1
22:33:11.897301 0 0 0

22:33:12.065294 4 4 90001
22:33:12.065294 1 110 0
22:33:12.065294 0 0 0

1
在尝试之前,您可能不应该将其接受为“解决方案” :) - sehe
1
我已经更新了代码以实际解码事件,并打印友好的微秒时间戳和事件批次。 (这是 Asio 如何透明地使用 POD 结构体向量作为写入缓冲区的一个示例。) - sehe
1
可能是日期时间。 (也许可以与第一个版本进行对比) - sehe
1
看起来所有的包含目录都是多余的,因为 /usr/include/ 已经在其中了。所以通常更合理的做法是使用 g++ -x c++ -std=c++11 -g -Wall -m32 -c asio_event_reader.cc -o asio_event_reader.o - sehe
1
@xinthose 看起来一次接收这样合理的事件批处理,最多。 - sehe
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接