Correctly report fixed point control values. Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> --- utils/v4l2-ctl/v4l2-ctl-common.cpp | 156 ++++++++++++++++++++++++----- 1 file changed, 131 insertions(+), 25 deletions(-) diff --git a/utils/v4l2-ctl/v4l2-ctl-common.cpp b/utils/v4l2-ctl/v4l2-ctl-common.cpp index c089c332..4b3308f3 100644 --- a/utils/v4l2-ctl/v4l2-ctl-common.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-common.cpp @@ -417,6 +417,55 @@ static bool fill_subset(const struct v4l2_query_ext_ctrl &qc, ctrl_subset &subse return false; } +static void print_fp(__s64 v, unsigned int fraction_bits) +{ + __s64 i, f, mask; + + if (!fraction_bits) { + printf("%lld", v); + return; + } + + mask = (1ULL << fraction_bits) - 1; + + /* + * Note: this function does not support fixed point u64 with + * fraction_bits set to 64. At the moment there is no U64 + * control type, but if that is added, then this code will have + * to add support for it. + */ + if (fraction_bits >= 63) + i = v < 0 ? -1 : 0; + else + i = v / (1LL << fraction_bits); + + f = (v & mask) ? (v < 0 ? -((-v) & mask) : (v & mask)) : 0; + + if (!f) { + printf("%lld", i); + } else if (fraction_bits < 20) { + __u64 div = 1ULL << fraction_bits; + + if (!i && f < 0) + printf("-%lld/%llu", -f, div); + else if (!i) + printf("%lld/%llu", f, div); + else if (i < 0 || f < 0) + printf("-%lld-%llu/%llu", -i, -f, div); + else + printf("%lld+%llu/%llu", i, f, div); + } else { + if (!i && f < 0) + printf("-%lld/(2^%u)", -f, fraction_bits); + else if (!i) + printf("%lld/(2^%u)", f, fraction_bits); + else if (i < 0 || f < 0) + printf("-%lld-%llu/(2^%u)", -i, -f, fraction_bits); + else + printf("%lld+%llu/(2^%u)", i, f, fraction_bits); + } +} + static void print_array(const v4l2_query_ext_ctrl &qc, const v4l2_ext_control &ctrl, const ctrl_subset &subset) { @@ -452,7 +501,10 @@ static void print_array(const v4l2_query_ext_ctrl &qc, const v4l2_ext_control &c switch (qc.type) { case V4L2_CTRL_TYPE_U8: for (i = from; i <= to; i++) { - printf("%4u", ctrl.p_u8[idx + i]); + if (qc.fraction_bits) + print_fp(ctrl.p_u8[idx + i], qc.fraction_bits); + else + printf("%4u", ctrl.p_u8[idx + i]); if (i < to) printf(", "); } @@ -460,7 +512,10 @@ static void print_array(const v4l2_query_ext_ctrl &qc, const v4l2_ext_control &c break; case V4L2_CTRL_TYPE_U16: for (i = from; i <= to; i++) { - printf("%6u", ctrl.p_u16[idx + i]); + if (qc.fraction_bits) + print_fp(ctrl.p_u16[idx + i], qc.fraction_bits); + else + printf("%6u", ctrl.p_u16[idx + i]); if (i < to) printf(", "); } @@ -468,7 +523,10 @@ static void print_array(const v4l2_query_ext_ctrl &qc, const v4l2_ext_control &c break; case V4L2_CTRL_TYPE_U32: for (i = from; i <= to; i++) { - printf("%10u", ctrl.p_u32[idx + i]); + if (qc.fraction_bits) + print_fp(ctrl.p_u32[idx + i], qc.fraction_bits); + else + printf("%10u", ctrl.p_u32[idx + i]); if (i < to) printf(", "); } @@ -476,7 +534,10 @@ static void print_array(const v4l2_query_ext_ctrl &qc, const v4l2_ext_control &c break; case V4L2_CTRL_TYPE_INTEGER: for (i = from; i <= to; i++) { - printf("%10i", ctrl.p_s32[idx + i]); + if (qc.fraction_bits) + print_fp(ctrl.p_s32[idx + i], qc.fraction_bits); + else + printf("%10d", ctrl.p_s32[idx + i]); if (i < to) printf(", "); } @@ -484,7 +545,10 @@ static void print_array(const v4l2_query_ext_ctrl &qc, const v4l2_ext_control &c break; case V4L2_CTRL_TYPE_INTEGER64: for (i = from; i <= to; i++) { - printf("%12lli", ctrl.p_s64[idx + i]); + if (qc.fraction_bits) + print_fp(ctrl.p_s64[idx + i], qc.fraction_bits); + else + printf("%12lld", ctrl.p_s64[idx + i]); if (i < to) printf(", "); } @@ -524,13 +588,13 @@ static void print_value(int fd, const v4l2_query_ext_ctrl &qc, const v4l2_ext_co if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) { switch (qc.type) { case V4L2_CTRL_TYPE_U8: - printf("%u", *ctrl.p_u8); + print_fp(*ctrl.p_u8, qc.fraction_bits); break; case V4L2_CTRL_TYPE_U16: - printf("%u", *ctrl.p_u16); + print_fp(*ctrl.p_u16, qc.fraction_bits); break; case V4L2_CTRL_TYPE_U32: - printf("%u", *ctrl.p_u32); + print_fp(*ctrl.p_u32, qc.fraction_bits); break; case V4L2_CTRL_TYPE_STRING: printf("'%s'", safename(ctrl.string).c_str()); @@ -546,7 +610,7 @@ static void print_value(int fd, const v4l2_query_ext_ctrl &qc, const v4l2_ext_co } switch (qc.type) { case V4L2_CTRL_TYPE_INTEGER64: - printf("%lld", ctrl.value64); + print_fp(ctrl.value64, qc.fraction_bits); break; case V4L2_CTRL_TYPE_MENU: case V4L2_CTRL_TYPE_INTEGER_MENU: @@ -561,7 +625,7 @@ static void print_value(int fd, const v4l2_query_ext_ctrl &qc, const v4l2_ext_co printf("%d (%lld 0x%llx)", ctrl.value, qmenu.value, qmenu.value); break; default: - printf("%d", ctrl.value); + print_fp(ctrl.value, qc.fraction_bits); break; } } @@ -574,14 +638,30 @@ static void print_qctrl(int fd, const v4l2_query_ext_ctrl &qc, switch (qc.type) { case V4L2_CTRL_TYPE_INTEGER: - printf("%31s %#8.8x (int) : min=%lld max=%lld step=%lld default=%lld", - s.c_str(), qc.id, qc.minimum, qc.maximum, - qc.step, qc.default_value); + printf("%31s %#8.8x (int) :", s.c_str(), qc.id); + if (qc.fraction_bits) { + printf(" min="); print_fp(qc.minimum, qc.fraction_bits); + printf(" max="); print_fp(qc.maximum, qc.fraction_bits); + printf(" step="); print_fp(qc.step, qc.fraction_bits); + printf(" default="); print_fp(qc.default_value, qc.fraction_bits); + } else { + printf(" min=%lld max=%lld step=%lld default=%lld", + qc.minimum, qc.maximum, + qc.step, qc.default_value); + } break; case V4L2_CTRL_TYPE_INTEGER64: - printf("%31s %#8.8x (int64) : min=%lld max=%lld step=%lld default=%lld", - s.c_str(), qc.id, qc.minimum, qc.maximum, - qc.step, qc.default_value); + printf("%31s %#8.8x (int64) :", s.c_str(), qc.id); + if (qc.fraction_bits) { + printf(" min="); print_fp(qc.minimum, qc.fraction_bits); + printf(" max="); print_fp(qc.maximum, qc.fraction_bits); + printf(" step="); print_fp(qc.step, qc.fraction_bits); + printf(" default="); print_fp(qc.default_value, qc.fraction_bits); + } else { + printf(" min=%lld max=%lld step=%lld default=%lld", + qc.minimum, qc.maximum, + qc.step, qc.default_value); + } break; case V4L2_CTRL_TYPE_STRING: printf("%31s %#8.8x (str) : min=%lld max=%lld step=%lld", @@ -609,19 +689,43 @@ static void print_qctrl(int fd, const v4l2_query_ext_ctrl &qc, s.c_str(), qc.id, qc.maximum, qc.default_value); break; case V4L2_CTRL_TYPE_U8: - printf("%31s %#8.8x (u8) : min=%lld max=%lld step=%lld default=%lld", - s.c_str(), qc.id, qc.minimum, qc.maximum, - qc.step, qc.default_value); + printf("%31s %#8.8x (u8) :", s.c_str(), qc.id); + if (qc.fraction_bits) { + printf(" min="); print_fp(qc.minimum, qc.fraction_bits); + printf(" max="); print_fp(qc.maximum, qc.fraction_bits); + printf(" step="); print_fp(qc.step, qc.fraction_bits); + printf(" default="); print_fp(qc.default_value, qc.fraction_bits); + } else { + printf(" min=%lld max=%lld step=%lld default=%lld", + qc.minimum, qc.maximum, + qc.step, qc.default_value); + } break; case V4L2_CTRL_TYPE_U16: - printf("%31s %#8.8x (u16) : min=%lld max=%lld step=%lld default=%lld", - s.c_str(), qc.id, qc.minimum, qc.maximum, - qc.step, qc.default_value); + printf("%31s %#8.8x (u16) :", s.c_str(), qc.id); + if (qc.fraction_bits) { + printf(" min="); print_fp(qc.minimum, qc.fraction_bits); + printf(" max="); print_fp(qc.maximum, qc.fraction_bits); + printf(" step="); print_fp(qc.step, qc.fraction_bits); + printf(" default="); print_fp(qc.default_value, qc.fraction_bits); + } else { + printf(" min=%lld max=%lld step=%lld default=%lld", + qc.minimum, qc.maximum, + qc.step, qc.default_value); + } break; case V4L2_CTRL_TYPE_U32: - printf("%31s %#8.8x (u32) : min=%lld max=%lld step=%lld default=%lld", - s.c_str(), qc.id, qc.minimum, qc.maximum, - qc.step, qc.default_value); + printf("%31s %#8.8x (u32) :", s.c_str(), qc.id); + if (qc.fraction_bits) { + printf(" min="); print_fp(qc.minimum, qc.fraction_bits); + printf(" max="); print_fp(qc.maximum, qc.fraction_bits); + printf(" step="); print_fp(qc.step, qc.fraction_bits); + printf(" default="); print_fp(qc.default_value, qc.fraction_bits); + } else { + printf(" min=%lld max=%lld step=%lld default=%lld", + qc.minimum, qc.maximum, + qc.step, qc.default_value); + } break; case V4L2_CTRL_TYPE_AREA: printf("%31s %#8.8x (area) :", s.c_str(), qc.id); @@ -710,6 +814,8 @@ static void print_qctrl(int fd, const v4l2_query_ext_ctrl &qc, for (i = 0; i < qc.nr_of_dims; i++) printf("[%u]", qc.dims[i]); } + if (qc.fraction_bits) + printf(" fraction_bits=%u", qc.fraction_bits); if (qc.flags) printf(" flags=%s", ctrlflags2s(qc.flags).c_str()); printf("\n"); -- 2.42.0