Search code examples
c++boostdebianboost-asiokeypad

boost::asio read from /dev/input/event0


I am looking to use boost::asio to read from a 12 digit keypad. I currently can do it without boost, this way:

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

Do you know how I could do this with boost::asio? I am using Linux and c++. This post and this post are useful. I would not use serial port port (io, "/dev/usb/hiddev0") because its not serial, right?

Thank you.


Solution

  • On my system, event2 represents the mouse, and the following simple readloop program works like a charm.

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

    Typical output:

    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