I'm working on a C program with joysticks and I'd like to get last event which is as the last line of js0 file. I'm trying to move my cursor before the last element but it doesn't seem working. Any idea why?
int fd = open ("/dev/input/js0", O_RDONLY);
struct js_event e;
lseek(fd, -(sizeof(e)), SEEK_END);
read (fd, &e, sizeof(e));
switch(e.type){
case JS_EVENT_BUTTON: printf("btn\n");
break;
case JS_EVENT_AXIS: printf("axes\n");
break;
default: printf("smth else\n");
}
I'm sure the file I'm reading is at least (sizeof(e)) long. Lseek returns me -1 so I got errno and it was 29 - Illegal seek: why should this be an illegal seek? I get the same results even if I use 0 as offset
lseek(fd, 0, SEEK_END)
I'm using last version Ubuntu, thanks for your help
why should this be an illegal seek?
The file you are trying to read from is a character special file (that's what the 'c' in the first position of its mode string indicates) by which the kernel's joystick driver can communicate with userspace programs, such as yours. Such files are like pipes -- not seekable. Any attempt to seek to a different position in such a file will fail, and some lseek()
implementations might fail even when the arguments correspond to zero net position change. You can find more information about device files here: What are character special and block special files in a unix system?
In comments, you ask
Any suggestion on how can I get last line?
, but that's unlikely to be what you actually want. In a file such as this one that represents a communication channel, reaching the end of the file (so as to be able to recognize the last line) indicates that the channel has been closed and all data have been read from it. No more data will ever be available via that file descriptor. That won't happen in your case under ordinary circumstances. And I doubt it is what you're hoping to observe.
What I think you want is to discover the most recent event available from the joystick device, and that's conceptually easy: you read events from the device until a read blocks, or would do. The Linux kernel documentation for the device you're using has some suggestions for avoiding blocking indefinitely:
Use select()
to determine whether data are available from the device before attempting to read from it.
Open the device in non-blocking mode (i.e. with option O_NONBLOCK
), and be prepared for your read()
s to fail (returning -1
) with errno
set to EAGAIN
.
Note that you should be checking the return value from read()
in any case, and that there is at least one other failure mode that is not necessarily a genuine error (EINTR
). Do read its manual page, as well as those of the other functions you're using, for details such as these.