As far as I know, ioctl numbers are well defined by the drivers and registered in the kernel.
I was playing with some code in python for querying joystick states. I have read this doc about joystick api, this doc about ioctl numbers, and this one from python fcntl module.
I’ve created a C program for testing and querying values, and the python tests with code that I took from here for implementing the _IOR() C macro.
Kernel driver define:
monolith@monolith ~/temp $ grep JSIOCGAXES /usr/include/* -r
/usr/include/linux/joystick.h:#define JSIOCGAXES _IOR('j', 0x11, __u8)
C program
#include <stdio.h>
#include <linux/joystick.h>
#include <fcntl.h>
int main() {
int fd = open("/dev/input/js0", O_RDONLY);
printf("Ioctl Number: (int)%d (hex)%x\n", JSIOCGAXES, JSIOCGAXES);
char number;
ioctl(fd, JSIOCGAXES, &number);
printf("Number of axes: %d\n", number);
close(fd);
return 0;
}
C program Output:
monolith@monolith ~/temp $ ./test
Ioctl Number: (int)-2147390959 (hex)80016a11
Number of axes: 6
Python output
# check if _IOR results in the used ioctl number in C
>>> _IOR(ord('j'), 0x11, 'c')
-2147390959
>>> file = open("/dev/input/js0")
# use that integer
>>> fcntl.ioctl(file, -2147390959)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 14] Bad address
# ask what hex value is
>>> "%x" % -2147390959
'-7ffe95ef'
# WHY THIS HEX CONVERSION DIFFERS?
>>> fcntl.ioctl(file, -0x7ffe95ef)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 14] Bad address
# Use the hex value from the C program output
>>> fcntl.ioctl(file, 0x80016a11)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 14] Bad address
Any ideas why I can’t query the file descriptor with that ioctl number? ioctl() and fcntl() functions take a file descriptor or an object with the fileno() method implemented so I discart the error from the file object.
Maybe the problem comes with number conversion and types, no idea…clues?
I’m going to answer my own question.
For some reason, the only way to get the value using
ioctl()from python was issuing this code:That is, using a buffer to sotre the result. I should re-read the documentation and understand why
fcntl.ioctl(file.fileno(), 0x80016a11)was not working.