ioctl-test: improve comments and add checks against ioctl num changes.
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 4 Feb 2013 12:56:02 +0000 (13:56 +0100)
committerHans Verkuil <hans.verkuil@cisco.com>
Mon, 4 Feb 2013 12:56:02 +0000 (13:56 +0100)
Improve the comments at the top of the source.

Also add explicit checks against the ioctl command values to verify that
they haven't changed after modifying structs used by existing ioctls.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
contrib/test/ioctl-test.c

index cb141c5..bceb8fd 100644 (file)
@@ -1,7 +1,18 @@
 /*
-   v4l-ioctl-test - This small utility sends dumb v4l2 ioctl to a device.
+   ioctl-test - This small utility sends dumb v4l2 ioctl to a device.
+
    It is meant to check ioctl debug messages generated and to check
-       if a function is implemented by that device.
+   if a function is implemented by that device. By compiling it as a
+   32-bit binary on a 64-bit architecture it can also be used to test
+   the 32-to-64 bit compat layer.
+
+   In addition it also checks that all the ioctl values haven't changed.
+   This tool should be run whenever a new ioctl is added, or when fields
+   are added to existing structs used by ioctls.
+
+   To compile as a 32-bit executable when on a 64-bit architecture use:
+
+       gcc -o ioctl-test32 ioctl-test.c -I../../include -m32
 
    Copyright (C) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
 
@@ -84,98 +95,100 @@ union v4l_parms {
        struct v4l2_exportbuffer p_v4l2_exportbuffer;
 };
 
-#define ioc(cmd) { cmd, #cmd }
+#define ioc(cmd32, cmd64, cmd) { cmd32, cmd64, cmd, #cmd }
 
 /* All defined ioctls */
 static const struct {
+       u_int32_t cmd32;        /* The 32-bit ioctl value, should never change */
+       u_int32_t cmd64;        /* The 64-bit ioctl value, should never change */
        u_int32_t cmd;
        const char *name;
 } ioctls[] = {
        /* V4L2 ioctls */
-       ioc(VIDIOC_QUERYCAP),           /* struct v4l2_capability */
-       ioc(VIDIOC_RESERVED),
-       ioc(VIDIOC_ENUM_FMT),           /* struct v4l2_fmtdesc */
-       ioc(VIDIOC_G_FMT),              /* struct v4l2_format */
-       ioc(VIDIOC_S_FMT),              /* struct v4l2_format */
-       ioc(VIDIOC_REQBUFS),            /* struct v4l2_requestbuffers */
-       ioc(VIDIOC_QUERYBUF),           /* struct v4l2_buffer */
-       ioc(VIDIOC_G_FBUF),             /* struct v4l2_framebuffer */
-       ioc(VIDIOC_S_FBUF),             /* struct v4l2_framebuffer */
-       ioc(VIDIOC_OVERLAY),            /* int */
-       ioc(VIDIOC_QBUF),               /* struct v4l2_buffer */
-       ioc(VIDIOC_EXPBUF),             /* struct v4l2_exportbuffer */
-       ioc(VIDIOC_DQBUF),              /* struct v4l2_buffer */
-       ioc(VIDIOC_STREAMON),           /* int */
-       ioc(VIDIOC_STREAMOFF),          /* int */
-       ioc(VIDIOC_G_PARM),             /* struct v4l2_streamparm */
-       ioc(VIDIOC_S_PARM),             /* struct v4l2_streamparm */
-       ioc(VIDIOC_G_STD),              /* v4l2_std_id */
-       ioc(VIDIOC_S_STD),              /* v4l2_std_id */
-       ioc(VIDIOC_ENUMSTD),            /* struct v4l2_standard */
-       ioc(VIDIOC_ENUMINPUT),          /* struct v4l2_input */
-       ioc(VIDIOC_G_CTRL),             /* struct v4l2_control */
-       ioc(VIDIOC_S_CTRL),             /* struct v4l2_control */
-       ioc(VIDIOC_G_TUNER),            /* struct v4l2_tuner */
-       ioc(VIDIOC_S_TUNER),            /* struct v4l2_tuner */
-       ioc(VIDIOC_G_AUDIO),            /* struct v4l2_audio */
-       ioc(VIDIOC_S_AUDIO),            /* struct v4l2_audio */
-       ioc(VIDIOC_QUERYCTRL),          /* struct v4l2_queryctrl */
-       ioc(VIDIOC_QUERYMENU),          /* struct v4l2_querymenu */
-       ioc(VIDIOC_G_INPUT),            /* int */
-       ioc(VIDIOC_S_INPUT),            /* int */
-       ioc(VIDIOC_G_OUTPUT),           /* int */
-       ioc(VIDIOC_S_OUTPUT),           /* int */
-       ioc(VIDIOC_ENUMOUTPUT),         /* struct v4l2_output */
-       ioc(VIDIOC_G_AUDOUT),           /* struct v4l2_audioout */
-       ioc(VIDIOC_S_AUDOUT),           /* struct v4l2_audioout */
-       ioc(VIDIOC_G_MODULATOR),        /* struct v4l2_modulator */
-       ioc(VIDIOC_S_MODULATOR),        /* struct v4l2_modulator */
-       ioc(VIDIOC_G_FREQUENCY),        /* struct v4l2_frequency */
-       ioc(VIDIOC_S_FREQUENCY),        /* struct v4l2_frequency */
-       ioc(VIDIOC_CROPCAP),            /* struct v4l2_cropcap */
-       ioc(VIDIOC_G_CROP),             /* struct v4l2_crop */
-       ioc(VIDIOC_S_CROP),             /* struct v4l2_crop */
-       ioc(VIDIOC_G_JPEGCOMP),         /* struct v4l2_jpegcompression */
-       ioc(VIDIOC_S_JPEGCOMP),         /* struct v4l2_jpegcompression */
-       ioc(VIDIOC_QUERYSTD),           /* v4l2_std_id */
-       ioc(VIDIOC_TRY_FMT),            /* struct v4l2_format */
-       ioc(VIDIOC_ENUMAUDIO),          /* struct v4l2_audio */
-       ioc(VIDIOC_ENUMAUDOUT),         /* struct v4l2_audioout */
-       ioc(VIDIOC_G_PRIORITY),         /* enum v4l2_priority */
-       ioc(VIDIOC_S_PRIORITY),         /* enum v4l2_priority */
-       ioc(VIDIOC_G_SLICED_VBI_CAP),   /* struct v4l2_sliced_vbi_cap */
-       ioc(VIDIOC_LOG_STATUS),
-       ioc(VIDIOC_G_EXT_CTRLS),        /* struct v4l2_ext_controls */
-       ioc(VIDIOC_S_EXT_CTRLS),        /* struct v4l2_ext_controls */
-       ioc(VIDIOC_TRY_EXT_CTRLS),      /* struct v4l2_ext_controls */
-       ioc(VIDIOC_ENUM_FRAMESIZES),    /* struct v4l2_frmsizeenum */
-       ioc(VIDIOC_ENUM_FRAMEINTERVALS),/* struct v4l2_frmivalenum */
-       ioc(VIDIOC_G_ENC_INDEX),        /* struct v4l2_enc_idx */
-       ioc(VIDIOC_ENCODER_CMD),        /* struct v4l2_encoder_cmd */
-       ioc(VIDIOC_TRY_ENCODER_CMD),    /* struct v4l2_encoder_cmd */
-       ioc(VIDIOC_DBG_S_REGISTER),     /* struct v4l2_register */
-       ioc(VIDIOC_DBG_G_REGISTER),     /* struct v4l2_register */
-       ioc(VIDIOC_DBG_G_CHIP_IDENT),   /* struct v4l2_dbg_chip_ident */
-       ioc(VIDIOC_S_HW_FREQ_SEEK),     /* struct v4l2_hw_freq_seek */
-       ioc(VIDIOC_ENUM_DV_PRESETS),    /* struct v4l2_dv_enum_preset */
-       ioc(VIDIOC_S_DV_PRESET),        /* struct v4l2_dv_preset */
-       ioc(VIDIOC_G_DV_PRESET),        /* struct v4l2_dv_preset */
-       ioc(VIDIOC_QUERY_DV_PRESET),    /* struct v4l2_dv_preset */
-       ioc(VIDIOC_S_DV_TIMINGS),       /* struct v4l2_dv_timings */
-       ioc(VIDIOC_G_DV_TIMINGS),       /* struct v4l2_dv_timings */
-       ioc(VIDIOC_DQEVENT),            /* struct v4l2_event */
-       ioc(VIDIOC_SUBSCRIBE_EVENT),    /* struct v4l2_event_subscription */
-       ioc(VIDIOC_UNSUBSCRIBE_EVENT),  /* struct v4l2_event_subscription */
-       ioc(VIDIOC_CREATE_BUFS),        /* struct v4l2_create_buffers */
-       ioc(VIDIOC_PREPARE_BUF),        /* struct v4l2_buffer */
-       ioc(VIDIOC_G_SELECTION),        /* struct v4l2_selection */
-       ioc(VIDIOC_S_SELECTION),        /* struct v4l2_selection */
-       ioc(VIDIOC_DECODER_CMD),        /* struct v4l2_decoder_cmd */
-       ioc(VIDIOC_TRY_DECODER_CMD),    /* struct v4l2_decoder_cmd */
-       ioc(VIDIOC_ENUM_DV_TIMINGS),    /* struct v4l2_enum_dv_timings */
-       ioc(VIDIOC_QUERY_DV_TIMINGS),   /* struct v4l2_dv_timings */
-       ioc(VIDIOC_DV_TIMINGS_CAP),     /* struct v4l2_dv_timings_cap */
-       ioc(VIDIOC_ENUM_FREQ_BANDS),    /* struct v4l2_frequency_band */
+       ioc(0x80685600, 0x80685600, VIDIOC_QUERYCAP),           /* struct v4l2_capability */
+       ioc(0x00005601, 0x00005601, VIDIOC_RESERVED),
+       ioc(0xc0405602, 0xc0405602, VIDIOC_ENUM_FMT),           /* struct v4l2_fmtdesc */
+       ioc(0xc0cc5604, 0xc0d05604, VIDIOC_G_FMT),              /* struct v4l2_format */
+       ioc(0xc0cc5605, 0xc0d05605, VIDIOC_S_FMT),              /* struct v4l2_format */
+       ioc(0xc0145608, 0xc0145608, VIDIOC_REQBUFS),            /* struct v4l2_requestbuffers */
+       ioc(0xc0445609, 0xc0585609, VIDIOC_QUERYBUF),           /* struct v4l2_buffer */
+       ioc(0x802c560a, 0x8030560a, VIDIOC_G_FBUF),             /* struct v4l2_framebuffer */
+       ioc(0x402c560b, 0x4030560b, VIDIOC_S_FBUF),             /* struct v4l2_framebuffer */
+       ioc(0x4004560e, 0x4004560e, VIDIOC_OVERLAY),            /* int */
+       ioc(0xc044560f, 0xc058560f, VIDIOC_QBUF),               /* struct v4l2_buffer */
+       ioc(0xc0405610, 0xc0405610, VIDIOC_EXPBUF),             /* struct v4l2_exportbuffer */
+       ioc(0xc0445611, 0xc0585611, VIDIOC_DQBUF),              /* struct v4l2_buffer */
+       ioc(0x40045612, 0x40045612, VIDIOC_STREAMON),           /* int */
+       ioc(0x40045613, 0x40045613, VIDIOC_STREAMOFF),          /* int */
+       ioc(0xc0cc5615, 0xc0cc5615, VIDIOC_G_PARM),             /* struct v4l2_streamparm */
+       ioc(0xc0cc5616, 0xc0cc5616, VIDIOC_S_PARM),             /* struct v4l2_streamparm */
+       ioc(0x80085617, 0x80085617, VIDIOC_G_STD),              /* v4l2_std_id */
+       ioc(0x40085618, 0x40085618, VIDIOC_S_STD),              /* v4l2_std_id */
+       ioc(0xc0405619, 0xc0485619, VIDIOC_ENUMSTD),            /* struct v4l2_standard */
+       ioc(0xc04c561a, 0xc050561a, VIDIOC_ENUMINPUT),          /* struct v4l2_input */
+       ioc(0xc008561b, 0xc008561b, VIDIOC_G_CTRL),             /* struct v4l2_control */
+       ioc(0xc008561c, 0xc008561c, VIDIOC_S_CTRL),             /* struct v4l2_control */
+       ioc(0xc054561d, 0xc054561d, VIDIOC_G_TUNER),            /* struct v4l2_tuner */
+       ioc(0x4054561e, 0x4054561e, VIDIOC_S_TUNER),            /* struct v4l2_tuner */
+       ioc(0x80345621, 0x80345621, VIDIOC_G_AUDIO),            /* struct v4l2_audio */
+       ioc(0x40345622, 0x40345622, VIDIOC_S_AUDIO),            /* struct v4l2_audio */
+       ioc(0xc0445624, 0xc0445624, VIDIOC_QUERYCTRL),          /* struct v4l2_queryctrl */
+       ioc(0xc02c5625, 0xc02c5625, VIDIOC_QUERYMENU),          /* struct v4l2_querymenu */
+       ioc(0x80045626, 0x80045626, VIDIOC_G_INPUT),            /* int */
+       ioc(0xc0045627, 0xc0045627, VIDIOC_S_INPUT),            /* int */
+       ioc(0x8004562e, 0x8004562e, VIDIOC_G_OUTPUT),           /* int */
+       ioc(0xc004562f, 0xc004562f, VIDIOC_S_OUTPUT),           /* int */
+       ioc(0xc0485630, 0xc0485630, VIDIOC_ENUMOUTPUT),         /* struct v4l2_output */
+       ioc(0x80345631, 0x80345631, VIDIOC_G_AUDOUT),           /* struct v4l2_audioout */
+       ioc(0x40345632, 0x40345632, VIDIOC_S_AUDOUT),           /* struct v4l2_audioout */
+       ioc(0xc0445636, 0xc0445636, VIDIOC_G_MODULATOR),        /* struct v4l2_modulator */
+       ioc(0x40445637, 0x40445637, VIDIOC_S_MODULATOR),        /* struct v4l2_modulator */
+       ioc(0xc02c5638, 0xc02c5638, VIDIOC_G_FREQUENCY),        /* struct v4l2_frequency */
+       ioc(0x402c5639, 0x402c5639, VIDIOC_S_FREQUENCY),        /* struct v4l2_frequency */
+       ioc(0xc02c563a, 0xc02c563a, VIDIOC_CROPCAP),            /* struct v4l2_cropcap */
+       ioc(0xc014563b, 0xc014563b, VIDIOC_G_CROP),             /* struct v4l2_crop */
+       ioc(0x4014563c, 0x4014563c, VIDIOC_S_CROP),             /* struct v4l2_crop */
+       ioc(0x808c563d, 0x808c563d, VIDIOC_G_JPEGCOMP),         /* struct v4l2_jpegcompression */
+       ioc(0x408c563e, 0x408c563e, VIDIOC_S_JPEGCOMP),         /* struct v4l2_jpegcompression */
+       ioc(0x8008563f, 0x8008563f, VIDIOC_QUERYSTD),           /* v4l2_std_id */
+       ioc(0xc0cc5640, 0xc0d05640, VIDIOC_TRY_FMT),            /* struct v4l2_format */
+       ioc(0xc0345641, 0xc0345641, VIDIOC_ENUMAUDIO),          /* struct v4l2_audio */
+       ioc(0xc0345642, 0xc0345642, VIDIOC_ENUMAUDOUT),         /* struct v4l2_audioout */
+       ioc(0x80045643, 0x80045643, VIDIOC_G_PRIORITY),         /* enum v4l2_priority */
+       ioc(0x40045644, 0x40045644, VIDIOC_S_PRIORITY),         /* enum v4l2_priority */
+       ioc(0xc0745645, 0xc0745645, VIDIOC_G_SLICED_VBI_CAP),   /* struct v4l2_sliced_vbi_cap */
+       ioc(0x00005646, 0x00005646, VIDIOC_LOG_STATUS),
+       ioc(0xc0185647, 0xc0205647, VIDIOC_G_EXT_CTRLS),        /* struct v4l2_ext_controls */
+       ioc(0xc0185648, 0xc0205648, VIDIOC_S_EXT_CTRLS),        /* struct v4l2_ext_controls */
+       ioc(0xc0185649, 0xc0205649, VIDIOC_TRY_EXT_CTRLS),      /* struct v4l2_ext_controls */
+       ioc(0xc02c564a, 0xc02c564a, VIDIOC_ENUM_FRAMESIZES),    /* struct v4l2_frmsizeenum */
+       ioc(0xc034564b, 0xc034564b, VIDIOC_ENUM_FRAMEINTERVALS),/* struct v4l2_frmivalenum */
+       ioc(0x8818564c, 0x8818564c, VIDIOC_G_ENC_INDEX),        /* struct v4l2_enc_idx */
+       ioc(0xc028564d, 0xc028564d, VIDIOC_ENCODER_CMD),        /* struct v4l2_encoder_cmd */
+       ioc(0xc028564e, 0xc028564e, VIDIOC_TRY_ENCODER_CMD),    /* struct v4l2_encoder_cmd */
+       ioc(0x4038564f, 0x4038564f, VIDIOC_DBG_S_REGISTER),     /* struct v4l2_register */
+       ioc(0xc0385650, 0xc0385650, VIDIOC_DBG_G_REGISTER),     /* struct v4l2_register */
+       ioc(0xc02c5651, 0xc02c5651, VIDIOC_DBG_G_CHIP_IDENT),   /* struct v4l2_dbg_chip_ident */
+       ioc(0x40305652, 0x40305652, VIDIOC_S_HW_FREQ_SEEK),     /* struct v4l2_hw_freq_seek */
+       ioc(0xc0405653, 0xc0405653, VIDIOC_ENUM_DV_PRESETS),    /* struct v4l2_dv_enum_preset */
+       ioc(0xc0145654, 0xc0145654, VIDIOC_S_DV_PRESET),        /* struct v4l2_dv_preset */
+       ioc(0xc0145655, 0xc0145655, VIDIOC_G_DV_PRESET),        /* struct v4l2_dv_preset */
+       ioc(0x80145656, 0x80145656, VIDIOC_QUERY_DV_PRESET),    /* struct v4l2_dv_preset */
+       ioc(0xc0845657, 0xc0845657, VIDIOC_S_DV_TIMINGS),       /* struct v4l2_dv_timings */
+       ioc(0xc0845658, 0xc0845658, VIDIOC_G_DV_TIMINGS),       /* struct v4l2_dv_timings */
+       ioc(0x80785659, 0x80885659, VIDIOC_DQEVENT),            /* struct v4l2_event */
+       ioc(0x4020565a, 0x4020565a, VIDIOC_SUBSCRIBE_EVENT),    /* struct v4l2_event_subscription */
+       ioc(0x4020565b, 0x4020565b, VIDIOC_UNSUBSCRIBE_EVENT),  /* struct v4l2_event_subscription */
+       ioc(0xc0f8565c, 0xc100565c, VIDIOC_CREATE_BUFS),        /* struct v4l2_create_buffers */
+       ioc(0xc044565d, 0xc058565d, VIDIOC_PREPARE_BUF),        /* struct v4l2_buffer */
+       ioc(0xc040565e, 0xc040565e, VIDIOC_G_SELECTION),        /* struct v4l2_selection */
+       ioc(0xc040565f, 0xc040565f, VIDIOC_S_SELECTION),        /* struct v4l2_selection */
+       ioc(0xc0485660, 0xc0485660, VIDIOC_DECODER_CMD),        /* struct v4l2_decoder_cmd */
+       ioc(0xc0485661, 0xc0485661, VIDIOC_TRY_DECODER_CMD),    /* struct v4l2_decoder_cmd */
+       ioc(0xc0945662, 0xc0945662, VIDIOC_ENUM_DV_TIMINGS),    /* struct v4l2_enum_dv_timings */
+       ioc(0x80845663, 0x80845663, VIDIOC_QUERY_DV_TIMINGS),   /* struct v4l2_dv_timings */
+       ioc(0xc0905664, 0xc0905664, VIDIOC_DV_TIMINGS_CAP),     /* struct v4l2_dv_timings_cap */
+       ioc(0xc0405665, 0xc0405665, VIDIOC_ENUM_FREQ_BANDS),    /* struct v4l2_frequency_band */
 };
 #define S_IOCTLS sizeof(ioctls)/sizeof(ioctls[0])
 
@@ -186,6 +199,7 @@ int main(int argc, char **argv)
        int fd = 0;
        unsigned i;
        unsigned maxlen = 0;
+       int cmd_errors = 0;
        char *device = "/dev/video0";
        char marker[8] = { 0xde, 0xad, 0xbe, 0xef, 0xad, 0xbc, 0xcb, 0xda };
        char p[sizeof(union v4l_parms) + 2 * sizeof(marker)];
@@ -198,14 +212,28 @@ int main(int argc, char **argv)
 
        if (argv[1])
                device = argv[1];
-       if ((fd = open(device, O_RDONLY|O_NONBLOCK)) < 0) {
-               fprintf(stderr, "Couldn't open %s\n", device);
-               return -1;
-       }
-
+       
        for (i = 0; i < S_IOCTLS; i++) {
+               unsigned cmp_cmd;
+
                if (strlen(ioctls[i].name) > maxlen)
                        maxlen = strlen(ioctls[i].name);
+               if (sizeof(long) == 4)
+                       cmp_cmd = ioctls[i].cmd32;
+               else
+                       cmp_cmd = ioctls[i].cmd64;
+               if (cmp_cmd != ioctls[i].cmd) {
+                       fprintf(stderr, "%s: ioctl is 0x%08x but should be 0x%08x!\n",
+                                       ioctls[i].name, ioctls[i].cmd, cmp_cmd);
+                       cmd_errors = 1;
+               }
+       }
+       if (cmd_errors)
+               return -1;
+
+       if ((fd = open(device, O_RDONLY|O_NONBLOCK)) < 0) {
+               fprintf(stderr, "Couldn't open %s\n", device);
+               return -1;
        }
 
        for (i = 0; i < S_IOCTLS; i++) {