]> granicus.if.org Git - strace/commitdiff
v4l2: improve control ID printing
authorEugene Syromyatnikov <evgsyr@gmail.com>
Sun, 19 Aug 2018 18:17:13 +0000 (20:17 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 5 Aug 2019 22:48:31 +0000 (22:48 +0000)
Control ID space is hierarchical, so, higher bits provide information
about control class.

* v4l2.c (print_v4l2_cid): New function.
(print_v4l2_control): Use print_v4l2_cid for printing control ID field.
* tests/ioctl_v4l2.c: Add checks for control ID printing.

tests/ioctl_v4l2.c
v4l2.c

index 54e9ee7c6bd933dc52873e6c111426211d104de3..5ddab1c6ce433939cd87c6bf78b9d48dcd125a91 100644 (file)
@@ -690,6 +690,23 @@ main(void)
        ioctl(-1, VIDIOC_G_CTRL, 0);
        printf("ioctl(-1, VIDIOC_G_CTRL, NULL) = -1 EBADF (%m)\n");
 
+       static const struct v4l2_control v4l2_control_vals[] = {
+               { .id = 0,                    .value = 3141592653U },
+               { .id = 0x97abcd,             .value = 1234567890U },
+               { .id = V4L2_CTRL_CLASS_USER, .value = 0 },
+               { .id = 0x990a64,             .value = 42 },
+               { .id = 0xa31234,             .value = 1 },
+               { .id = 0xa40000,             .value = -1 },
+       };
+       static const char *id_strs[] = {
+               "0 /* V4L2_CID_??? */",
+               "0x97abcd /* V4L2_CID_??? */",
+               "V4L2_CTRL_CLASS_USER+0",
+               "V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE",
+               "V4L2_CTRL_CLASS_DETECT+0x1234",
+               "0xa40000 /* V4L2_CID_??? */",
+       };
+
        struct v4l2_control *const p_v4l2_control =
                page_end - sizeof(*p_v4l2_control);
        ioctl(-1, VIDIOC_G_CTRL, p_v4l2_control);
@@ -705,6 +722,19 @@ main(void)
               ", value=%d}) = -1 EBADF (%m)\n",
               p_v4l2_control->id, p_v4l2_control->value);
 
+       for (size_t i = 0; i < ARRAY_SIZE(id_strs); i++) {
+               struct v4l2_control v4l2_c = v4l2_control_vals[i];
+
+               ioctl(-1, VIDIOC_G_CTRL, &v4l2_c);
+               printf("ioctl(-1, VIDIOC_G_CTRL, {id=%s}) = -1 EBADF (%m)\n",
+                      id_strs[i]);
+
+               ioctl(-1, VIDIOC_S_CTRL, &v4l2_c);
+               printf("ioctl(-1, VIDIOC_S_CTRL, {id=%s, value=%d})"
+                      " = -1 EBADF (%m)\n",
+                      id_strs[i], v4l2_c.value);
+       }
+
        /* VIDIOC_G_TUNER */
        ioctl(-1, VIDIOC_G_TUNER, 0);
        printf("ioctl(-1, VIDIOC_G_TUNER, NULL) = -1 EBADF (%m)\n");
diff --git a/v4l2.c b/v4l2.c
index b325cf8b3606da5e0caa9e02a6211c0437d58af7..5da457c66e1d626c46323243117652fe62e4b556 100644 (file)
--- a/v4l2.c
+++ b/v4l2.c
@@ -598,6 +598,34 @@ print_v4l2_input(struct tcb *const tcp, const kernel_ulong_t arg)
 #include "xlat/v4l2_control_id_bases.h"
 #include "xlat/v4l2_control_ids.h"
 
+static void
+print_v4l2_cid(const uint32_t cid)
+{
+       const char *id_name = xlookup(v4l2_control_ids, cid);
+
+       if (id_name) {
+               print_xlat_ex(cid, id_name, XLAT_STYLE_DEFAULT);
+               return;
+       }
+
+       uint64_t class_id = cid;
+       const char *class_str = xlookup_le(v4l2_control_classes, &class_id);
+
+       if (!class_str || (cid - class_id) >= 0x10000) {
+               print_xlat_ex(cid, "V4L2_CID_???", PXF_DEFAULT_STR);
+               return;
+       }
+
+       char *tmp_str;
+
+       if (asprintf(&tmp_str, "%s+%#" PRIx64,
+                    class_str, cid - class_id) < 0)
+               tmp_str = NULL;
+
+       print_xlat_ex(cid, tmp_str, XLAT_STYLE_DEFAULT);
+       free(tmp_str);
+}
+
 static int
 print_v4l2_control(struct tcb *const tcp, const kernel_ulong_t arg,
                   const bool is_get)
@@ -608,8 +636,9 @@ print_v4l2_control(struct tcb *const tcp, const kernel_ulong_t arg,
                tprints(", ");
                if (umove_or_printaddr(tcp, arg, &c))
                        return RVAL_IOCTL_DECODED;
+
                tprints("{id=");
-               printxval(v4l2_control_ids, c.id, "V4L2_CID_???");
+               print_v4l2_cid(c.id);
                if (!is_get)
                        tprintf(", value=%d", c.value);
                return 0;