0

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.

10
  • 2
    How have you opened the file descriptor? Commented Aug 4, 2017 at 14:37
  • 2
    2 options - select(2) or threads. Commented Aug 4, 2017 at 14:38
  • @EugeneSh. I have opened it with: device = "/dev/input/js0"; js = open(device, O_RDONLY); as in the original link. Commented Aug 4, 2017 at 14:43
  • 5
    @JanusGowda it is normal that read() blocks until it can transfer at least one byte, except for files that are open in non-blocking mode. You should be able to open the device in non-blocking mode by including the flag O_NONBLOCK in the options bitmask you pass to open(). Commented Aug 4, 2017 at 14:45
  • 1
    @JanusGowda yes, read waits until data is available to be read. Commented Aug 4, 2017 at 14:46

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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);
}

2 Comments

This is very wrong. Because data might become unavailable after the is_event_buffer_empy() - Some other thread reading it.
The OP is reading via a file descriptor, not a stream, so there is no stream buffer (unless he implements one himself). Even if there were, the buffer being empty is not the same thing as there being no data available to read.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.