11

I have a Linux standard header file e.g.

/usr/src/linux-headers-3.2.0-35/include/linux/usbdevice_fs.h

which contain define statements as follows:

#define USBDEVFS_SUBMITURB32       _IOR('U', 10, struct usbdevfs_urb32)
#define USBDEVFS_DISCARDURB        _IO('U', 11)
#define USBDEVFS_REAPURB           _IOW('U', 12, void *)

What does '_IOR', '_IO' and '_IOW' mean? What value is actually given e.g. to USBDEVFS_DISCARDURB?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Alex
  • 41,580
  • 88
  • 260
  • 469

2 Answers2

9

They define ioctl numbers, based on ioctl function and input parameters. The are defined in kernel, in include/asm-generic/ioctl.h.

You need to include <linux/ioctl.h> (or linux/asm-generic/ioctl.h) in your program. Before including
/usr/src/linux-headers-3.2.0-35/include/linux/usbdevice_fs.h

You can't "precompile" this values (e.g. USBDEVFS_DISCARDURB), because they can be different on other platforms. For example, you are developing your code on plain old x86, but then someone will try to use it on x86_64/arm/mips/etc. So you should always include kernel's ioctl.h to make sure, you are using right values.

werewindle
  • 3,009
  • 17
  • 27
  • Now we are getting close. Including this particular header file I was able to compute the numerical value of the `_IO` construct. – Alex Jan 31 '13 at 14:29
  • 1
    @Alex, but be beware, that numerical value possibly can be changed in next kernel version (e.g. sizeof struct usbdevfs_urb32 will be changed). You'd better always include this two files and use defined name. – werewindle Jan 31 '13 at 14:40
  • 3
    The IOCTLs are supposed to stay stable from version to version because they represent a user ABI. Old binaries must work on new kernels. However the IOCTL values differ on various platforms and that is why one should use the values from the headers: to stay portable across many platforms. – goertzenator Apr 01 '16 at 14:21
  • @goertzenator, yes, you are right in general. I was speaking as embedded developer. There are lots of strange things can happen during active development. I have seen how IOCTL values changed on the same kernel version, but yes, it was rather exceptional case. I'll update the answer. – werewindle Apr 21 '16 at 12:08
1

These are also macros defined elsewhere.

In general if you want to see your code after pre-processor has been computed use

gcc -E foo.c

this will output your code pre-processed

For example:

foo.c

#define FORTY_TWO 42

int main(void)
{
  int foo = FORTY_TWO;
}

will give you with gcc -E foo.c:

int main(void)
{
  int foo = 42;
}
Eregrith
  • 4,263
  • 18
  • 39
  • I cannot see the variable `USBDEVFS_DISCARDURB` in the output of `gcc -E /usr/src/linux-headers-3.2.0-35/include/linux/usbdevice_fs.h` anymore. How can I see the actual value? Or how can I find out where those macros are defined? – Alex Jan 31 '13 at 13:35
  • If you want to also see the macro definitions and the `#include` statements, add the `-dDI` flag. To prevent macro expansion, make it `-dDNI` – Michael Wild Jan 31 '13 at 13:35
  • @Alex See my edit; you wouldn't see the macro USBDEVFS_DISCARDURB because `gcc -E` has preprocessed it and replaced it in-place by its value. `gcc -E` is also not supposed to be used on a header file but on a source file as stated in my answer. – Eregrith Jan 31 '13 at 13:40
  • @Eregrith: I understand what `gcc -E` is doing, but it does not answer my question. I still need to find out the value of the variable `USBDEVFS_DISCARDURB` for example, or to find the definition of the `_IO` command (to derive the value myself). – Alex Jan 31 '13 at 13:42
  • 1
    Daft question but can't you just add a `USBDEVFS_DISCARDURB` to your source file then preprocess it? Your change doesn't have to compile; you can delete it as soon as you've seen the preprocessor output. – simonc Jan 31 '13 at 13:53
  • @simonc: Your suggestion worked, but did not answer my question. It turned out that `USBDEVFS_DISCARDURB=_IO('U', 20)`! But what IS `_IO('U', 20)`? I am expecting an int value. – Alex Jan 31 '13 at 14:00
  • Then it proves that `_IO('U', 20)` is not a macro but indeed a function – Eregrith Jan 31 '13 at 14:01
  • @Eregrith: Interesting subtlety, but it still does not answer my question. I need a numerical value (an int) that this variable stands for. – Alex Jan 31 '13 at 14:05
  • If you expect an `int` and just need its value why not simply `printf("%i\n", _IO('U', 20));`? – Eregrith Jan 31 '13 at 14:17
  • @Eregrith: Because I have to compile the code. I get a lot of errors, and it is just a header. But I guess I have no choice to write some c code which imports the header code and try to sort out all of the errors... – Alex Jan 31 '13 at 14:19