Making Linux system calls: What is the current way to do it?

I have a little C programme to operate a foot pedal that presents as a USB keyboard.

It uses: select, memset, and ioctl/EVIOCGKEY. I am very inexperienced with this sort of programming and it took me a long time to get it going in C. I would like to do this in rust but am unsure how. There is a confusing array of crates out there and I am unsure how it is best to proceed.

My algorithm is:

fd = open device
loop {
  block_on_data_available(fd)
  key = key_pressed_IOCTL(fd)
  act_on_it(key)
  read_all_data(fd)
}

More verbosely the C code is (all the error checking and variable declaration stripped out)

  fd = open("/dev/input/event0", O_RDONLY);
  while(1){
    tv.tv_sec = 200;
    tv.tv_usec = 0;
    FD_ZERO(&rfds);
    FD_SET(fd, &rfds);
    retval = select(fd+1, &rfds, NULL, NULL, &tv);
    if(retval == 0){
      continue;
    }
     memset(key_b, 0, sizeof(key_b));
    ioctl(fd, EVIOCGKEY(sizeof(key_b)), key_b);
    for (yalv = 0; yalv < KEY_MAX; yalv++) {
      if (test_bit(yalv, key_b)) {
          if(yalv == 0x1e){
            doit('A');
          }else if(yalv == 0x30){
            doit('B');
         }
      read(fd, &buf, buff_size);
    }

Roughly

You could use the libc crate to make the equivalent calls, but if you want to try something higher level, you could try to use the mio library as a wrapper around select, or even use Tokio via its AsyncFd type.

1 Like

There's also nix, which allows you to avoid the unsafe {} blocks, although in my personal (albeit limited) experience I ended up dropping it in favor of using libc directly.

1 Like

Helpful.

Using libc::ioctl to read interface flags looks like what I am looking for.