From af612e43de6d27df51a7636229be7d33fe3ab7b5 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 16 Feb 2021 17:57:20 +0200 Subject: lib/vsprintf: Add support for printing V4L2 and DRM fourccs Add a printk modifier %p4cc (for pixel format) for printing V4L2 and DRM pixel formats denoted by fourccs. The fourcc encoding is the same for both so the same implementation can be used. Suggested-by: Mauro Carvalho Chehab Signed-off-by: Sakari Ailus Reviewed-by: Petr Mladek Reviewed-by: Sergey Senozhatsky Reviewed-by: Andy Shevchenko Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20210216155723.17109-2-sakari.ailus@linux.intel.com --- lib/vsprintf.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3b53c73580c5..62c7224a5076 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1733,6 +1733,42 @@ char *netdev_bits(char *buf, char *end, const void *addr, return special_hex_number(buf, end, num, size); } +static noinline_for_stack +char *fourcc_string(char *buf, char *end, const u32 *fourcc, + struct printf_spec spec, const char *fmt) +{ + char output[sizeof("0123 little-endian (0x01234567)")]; + char *p = output; + unsigned int i; + u32 val; + + if (fmt[1] != 'c' || fmt[2] != 'c') + return error_string(buf, end, "(%p4?)", spec); + + if (check_pointer(&buf, end, fourcc, spec)) + return buf; + + val = *fourcc & ~BIT(31); + + for (i = 0; i < sizeof(*fourcc); i++) { + unsigned char c = val >> (i * 8); + + /* Print non-control ASCII characters as-is, dot otherwise */ + *p++ = isascii(c) && isprint(c) ? c : '.'; + } + + strcpy(p, *fourcc & BIT(31) ? " big-endian" : " little-endian"); + p += strlen(p); + + *p++ = ' '; + *p++ = '('; + p = special_hex_number(p, output + sizeof(output) - 2, *fourcc, sizeof(u32)); + *p++ = ')'; + *p = '\0'; + + return string(buf, end, output, spec); +} + static noinline_for_stack char *address_val(char *buf, char *end, const void *addr, struct printf_spec spec, const char *fmt) @@ -2162,6 +2198,7 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode, * correctness of the format string and va_list arguments. * - 'K' For a kernel pointer that should be hidden from unprivileged users * - 'NF' For a netdev_features_t + * - '4cc' V4L2 or DRM FourCC code, with endianness and raw numerical value. * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with * a certain separator (' ' by default): * C colon @@ -2259,6 +2296,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, return restricted_pointer(buf, end, ptr, spec); case 'N': return netdev_bits(buf, end, ptr, spec, fmt); + case '4': + return fourcc_string(buf, end, ptr, spec, fmt); case 'a': return address_val(buf, end, ptr, spec, fmt); case 'd': -- cgit v1.2.3