Rosario 3D

My developer blog

Who need focus?

I’m trying to read get data from various devices for my engine, but I didn’t find a good way to read joystick data with Xlib. Then I read about Evdev.

Basically you can read the files called /dev/input/event* to get the data, it read almost everything, mouse, keyboard, tablet, joystick, wheel.. And the good thing is that it fit perfectly with the multi thread event environment I wrote for my engine.
With ioctl you can get some information about the device *name, id, driver version…)
Then you can read the structure input_event from the file.

The cool thigh about evdev is that you are reading the raw data from the device, so you don’t need the focus.

You can check the linux/input.h file to check the data you can read from the input_event structure.

Here some dirt and quick test, the select is used to check more files/device simultaneously.
The code is based on evtest.

#include <linux/input.h>
#include <algorithm>
#include <vector>
#include <iostream>

#include <fcntl.h>
#include <cstring>

struct DeviceHandle{
  int file_;
  char deviceName_[256];
};
using namespace std;

int main( int argc, char **argv)
{
  int nfds = 0;
  vector<DeviceHandle> handle;
  fd_set readSet;
  FD_ZERO(&readSet);
  if(argc-1 <= 0){
    cerr << "You must specify some file\n";
    return EXIT_FAILURE;
  }
  for(unsigned int i = 1; i < argc; ++i){
    int file;
    if((file = open(argv[i], O_RDONLY)) >= 0 ){
      nfds = std::max(nfds, file);
      DeviceHandle dh;
      if(ioctl(file, EVIOCGNAME(sizeof(handle[i].deviceName_)), dh.deviceName_) < 0)
        strcpy(dh.deviceName_, "Unknow");
      dh.file_ = file;
      handle.push_back(dh);
      FD_SET(file, &readSet);
    }else{
      cerr << argv[i] << " is not a valid file or permission denied.\n" ;
    }
  }
  if(handle.size() == 0){
    cerr << "No valid files\n";
    return EXIT_FAILURE;
  }
  while(1){
    struct input_event ev[64];
    int ifd = select(nfds, &readSet, NULL, NULL, NULL);
    if(ifd < 0){
      cerr << "Select fail\n";
      return EXIT_FAILURE;
    }else {
      for(auto it = handle.begin(); it != handle.end(); ++it){
        if(FD_ISSET(it->file_, &readSet)){
          cout << "Event from: " << it->deviceName_ << std::endl;
          int rd = read(it->file_, ev, sizeof(input_event) * 64);
          rd /= sizeof(input_event);
          for(unsigned int j = 0; j < rd; ++j)
            cout << "Time : " << ev[j].time.tv_sec << "." << ev[j].time.tv_usec << "  == Type: "  << ev[j].type << endl;
        }
      }
    }
    for(auto it = handle.begin(); it != handle.end(); ++it)
      FD_SET(it->file_, &readSet);
  }
  for(auto it = handle.begin(); it != handle.end(); ++it)
    close(it->file_);
  return EXIT_SUCCESS;
}

To compile
gcc evdev.cpp -std=c++0x -lstdc++ -o evdevtest
and then
sudo evdevtest /dev/input/event*
-Enjoy

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: