Janus Gowda
Janus Gowda

Reputation: 305

Use read() C function without stopping code

I'm trying to read data from a joystick using C code. I have found online the way to do it.

This solution seems to work fine but with a problem. When the code reachers the the read() function, it stops and waits until there is change in the joystick device:

int read_event(int fd, struct js_event *event)
{
    ssize_t bytes;

    bytes = read(fd, event, sizeof(*event));
    if (bytes == sizeof(*event))
        return 0;
    return -1;
}

I'm trying to find a way to make the code run continously and if there is no change in the control device, just return the previous state. So far I did not succeed. Maybe someone can help.

Upvotes: 0

Views: 647

Answers (2)

John Bollinger
John Bollinger

Reputation: 180048

Given that you are opening the joystick device via open() and reading from it via read(), I infer that you are coding for a machine that implements a POSIX interface. For most files, the POSIX read() function blocks until it can transfer at least one byte, and that is indeed the behavior you observe.

One way to avoid that is to open the file in non-blocking mode, or to put it in non-blocking mode after opening it but before reading it. You can do the former by adding the O_NONBLOCK flag to your open options:

 js = open(device, O_RDONLY | O_NONBLOCK);

That should interact cleanly and favorably with your existing code for reading joystick events. In the case that no event is available to read, your read() call should return immediately, with return value -1, and errno set to EAGAIN. Otherwise, it will return the number of bytes transferred.

Note that in general, read() is not guaranteed to transfer the full number of bytes you request -- it may successfully read fewer, which you can determine from its return value, and if you don't account for that then you can come to grief. I don't think you'll see any short reads from the joystick device, however; you should get either a complete event or nothing.

Upvotes: 2

iBug
iBug

Reputation: 37217

I'm not sure about the actual API (system call) function, but my idea should work.

Use something like GetNumberOfInputEvents (a WinAPI function) to determine whether your read will get stuck (with nothing to read). Then if you judge that it'll get stuck, skip it.

See Checking the stdin buffer if it's empty for more information.

Pseudo code:

read_event(Event* event){
    if (is_event_buffer_empty())
        // Do nothing because `read` is stuck
    else
        SystemAPI_ReadEvent(event);
}

Upvotes: 0

Related Questions