2020-04-01 14:14:43

by Hans Verkuil

[permalink] [raw]
Subject: Re: [PATCH 1/1] lib/vsprintf: Add support for printing V4L2 and DRM fourccs

On 4/1/20 4:05 PM, Sakari Ailus wrote:
> Add a printk modifier %ppf (for pixel format) for printing V4L2 and DRM
> pixel formats denoted by 4ccs. The 4cc encoding is the same for both so
> the same implementation can be used.
>
> Suggested-by: Mauro Carvalho Chehab <[email protected]>
> Signed-off-by: Sakari Ailus <[email protected]>
> ---
> Documentation/core-api/printk-formats.rst | 11 +++++++++
> lib/vsprintf.c | 29 +++++++++++++++++++++++
> 2 files changed, 40 insertions(+)
>
> diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
> index 8ebe46b1af39..b6249f513c09 100644
> --- a/Documentation/core-api/printk-formats.rst
> +++ b/Documentation/core-api/printk-formats.rst
> @@ -545,6 +545,17 @@ For printing netdev_features_t.
>
> Passed by reference.
>
> +V4L2 and DRM fourcc code (pixel format)
> +---------------------------------------
> +
> +::
> +
> + %ppf
> +
> +Print a 4cc code used by V4L2 or DRM.

FourCC appears to be the more-or-less official name (https://en.wikipedia.org/wiki/FourCC)

I would explain about the -BE suffix for bigendian fourcc variants.

> +
> +Passed by reference.
> +
> Thanks
> ======
>
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 7c488a1ce318..b39f0ac317c5 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1721,6 +1721,32 @@ char *netdev_bits(char *buf, char *end, const void *addr,
> return special_hex_number(buf, end, num, size);
> }
>
> +static noinline_for_stack
> +char *pixel_format_string(char *buf, char *end, const u32 *fourcc,
> + struct printf_spec spec, const char *fmt)
> +{
> + char ch[2] = { 0 };

This can just be '{ };'

> + unsigned int i;
> +
> + if (check_pointer(&buf, end, fourcc, spec))
> + return buf;
> +
> + switch (fmt[1]) {
> + case 'f':
> + for (i = 0; i < sizeof(*fourcc); i++) {
> + ch[0] = *fourcc >> (i << 3);

You need to AND with 0x7f, otherwise a big endian fourcc (bit 31 is set)
will look wrong. Also, each character is standard 7 bit ascii, bit 7 isn't
used except to indicate a BE variant.

> + buf = string(buf, end, ch, spec);
> + }
> +
> + if (*fourcc & BIT(31))
> + buf = string(buf, end, "-BE", spec);
> +
> + return buf;
> + default:
> + return error_string(buf, end, "(%pp?)", spec);
> + }
> +}
> +
> static noinline_for_stack
> char *address_val(char *buf, char *end, const void *addr,
> struct printf_spec spec, const char *fmt)
> @@ -2131,6 +2157,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
> + * - 'pf' V4L2 or DRM pixel format.

I'd say 'FourCC format' instead of 'pixel format'.

> * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
> * a certain separator (' ' by default):
> * C colon
> @@ -2223,6 +2250,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 'p':
> + return pixel_format_string(buf, end, ptr, spec, fmt);
> case 'a':
> return address_val(buf, end, ptr, spec, fmt);
> case 'd':
>

Regards,

Hans


2020-04-01 15:14:12

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH 1/1] lib/vsprintf: Add support for printing V4L2 and DRM fourccs

On Wed, Apr 01, 2020 at 04:13:51PM +0200, Hans Verkuil wrote:
> On 4/1/20 4:05 PM, Sakari Ailus wrote:
> > Add a printk modifier %ppf (for pixel format) for printing V4L2 and DRM
> > pixel formats denoted by 4ccs. The 4cc encoding is the same for both so
> > the same implementation can be used.

%p4cc ?

> > + char ch[2] = { 0 };
>
> This can just be '{ };'

The latter is GCC extension, while above is C standard. Former is slightly
better I think. Though see below.

> > + unsigned int i;
> > +
> > + if (check_pointer(&buf, end, fourcc, spec))
> > + return buf;
> > +
> > + switch (fmt[1]) {
> > + case 'f':

> > + for (i = 0; i < sizeof(*fourcc); i++) {
> > + ch[0] = *fourcc >> (i << 3);
>
> You need to AND with 0x7f, otherwise a big endian fourcc (bit 31 is set)
> will look wrong. Also, each character is standard 7 bit ascii, bit 7 isn't
> used except to indicate a BE variant.

Why not to do it once by a flag and do reset it once?

u32 tmp = *fourcc;
bool be4cc = tmp & BIT(31);

tmp &= BIT(31);

On top of that, as promised above, why not simple do it in a simpler way, i.e.
using standard idiom:

for (i = 0; i < sizeof(*fourcc); i++) {
if (buf < end)
*buf = tmp >> (i * 8);
buf++;
}
?

> > + buf = string(buf, end, ch, spec);
> > + }
> > +
> > + if (*fourcc & BIT(31))
> > + buf = string(buf, end, "-BE", spec);

Another possibility

u8 ch[8];

if (*fourcc & BIT(31)) {
put_unaligned_be32(tmp, &ch[0]);
strcpy(&ch[4], "-BE");
} else {
put_unaligned_le32(tmp, &ch[0]);
strcpy(&ch[4], "-LE");
}
return string(buf, end, &ch[0], spec);

> > + return buf;
> > + default:
> > + return error_string(buf, end, "(%pp?)", spec);
> > + }
> > +}

--
With Best Regards,
Andy Shevchenko


2020-04-02 07:19:34

by Sakari Ailus

[permalink] [raw]
Subject: Re: [PATCH 1/1] lib/vsprintf: Add support for printing V4L2 and DRM fourccs

Hi Hans,

Thank you for the review.

On Wed, Apr 01, 2020 at 04:13:51PM +0200, Hans Verkuil wrote:
> On 4/1/20 4:05 PM, Sakari Ailus wrote:
> > Add a printk modifier %ppf (for pixel format) for printing V4L2 and DRM
> > pixel formats denoted by 4ccs. The 4cc encoding is the same for both so
> > the same implementation can be used.
> >
> > Suggested-by: Mauro Carvalho Chehab <[email protected]>
> > Signed-off-by: Sakari Ailus <[email protected]>
> > ---
> > Documentation/core-api/printk-formats.rst | 11 +++++++++
> > lib/vsprintf.c | 29 +++++++++++++++++++++++
> > 2 files changed, 40 insertions(+)
> >
> > diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
> > index 8ebe46b1af39..b6249f513c09 100644
> > --- a/Documentation/core-api/printk-formats.rst
> > +++ b/Documentation/core-api/printk-formats.rst
> > @@ -545,6 +545,17 @@ For printing netdev_features_t.
> >
> > Passed by reference.
> >
> > +V4L2 and DRM fourcc code (pixel format)
> > +---------------------------------------
> > +
> > +::
> > +
> > + %ppf
> > +
> > +Print a 4cc code used by V4L2 or DRM.
>
> FourCC appears to be the more-or-less official name (https://en.wikipedia.org/wiki/FourCC)
>
> I would explain about the -BE suffix for bigendian fourcc variants.

Agreed, I'll address these in v2.

>
> > +
> > +Passed by reference.
> > +
> > Thanks
> > ======
> >
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > index 7c488a1ce318..b39f0ac317c5 100644
> > --- a/lib/vsprintf.c
> > +++ b/lib/vsprintf.c
> > @@ -1721,6 +1721,32 @@ char *netdev_bits(char *buf, char *end, const void *addr,
> > return special_hex_number(buf, end, num, size);
> > }
> >
> > +static noinline_for_stack
> > +char *pixel_format_string(char *buf, char *end, const u32 *fourcc,
> > + struct printf_spec spec, const char *fmt)
> > +{
> > + char ch[2] = { 0 };
>
> This can just be '{ };'

As Andy, I also do prefer { 0 }.

>
> > + unsigned int i;
> > +
> > + if (check_pointer(&buf, end, fourcc, spec))
> > + return buf;
> > +
> > + switch (fmt[1]) {
> > + case 'f':
> > + for (i = 0; i < sizeof(*fourcc); i++) {
> > + ch[0] = *fourcc >> (i << 3);
>
> You need to AND with 0x7f, otherwise a big endian fourcc (bit 31 is set)
> will look wrong. Also, each character is standard 7 bit ascii, bit 7 isn't
> used except to indicate a BE variant.

Good point, will fix for v2.

>
> > + buf = string(buf, end, ch, spec);
> > + }
> > +
> > + if (*fourcc & BIT(31))
> > + buf = string(buf, end, "-BE", spec);
> > +
> > + return buf;
> > + default:
> > + return error_string(buf, end, "(%pp?)", spec);
> > + }
> > +}
> > +
> > static noinline_for_stack
> > char *address_val(char *buf, char *end, const void *addr,
> > struct printf_spec spec, const char *fmt)
> > @@ -2131,6 +2157,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
> > + * - 'pf' V4L2 or DRM pixel format.
>
> I'd say 'FourCC format' instead of 'pixel format'.

Will fix.

--
Regards,

Sakari Ailus

2020-04-02 07:33:52

by Sakari Ailus

[permalink] [raw]
Subject: Re: [PATCH 1/1] lib/vsprintf: Add support for printing V4L2 and DRM fourccs

Hi Andy,

Thanks for the review.

On Wed, Apr 01, 2020 at 06:13:32PM +0300, Andy Shevchenko wrote:
> On Wed, Apr 01, 2020 at 04:13:51PM +0200, Hans Verkuil wrote:
> > On 4/1/20 4:05 PM, Sakari Ailus wrote:
> > > Add a printk modifier %ppf (for pixel format) for printing V4L2 and DRM
> > > pixel formats denoted by 4ccs. The 4cc encoding is the same for both so
> > > the same implementation can be used.
>
> %p4cc ?

Sounds good. Numbers have special handling but AFAIR only right after %
sign, so this should be possible.

>
> > > + char ch[2] = { 0 };
> >
> > This can just be '{ };'
>
> The latter is GCC extension, while above is C standard. Former is slightly
> better I think. Though see below.
>
> > > + unsigned int i;
> > > +
> > > + if (check_pointer(&buf, end, fourcc, spec))
> > > + return buf;
> > > +
> > > + switch (fmt[1]) {
> > > + case 'f':
>
> > > + for (i = 0; i < sizeof(*fourcc); i++) {
> > > + ch[0] = *fourcc >> (i << 3);
> >
> > You need to AND with 0x7f, otherwise a big endian fourcc (bit 31 is set)
> > will look wrong. Also, each character is standard 7 bit ascii, bit 7 isn't
> > used except to indicate a BE variant.
>
> Why not to do it once by a flag and do reset it once?
>
> u32 tmp = *fourcc;
> bool be4cc = tmp & BIT(31);
>
> tmp &= BIT(31);

I had two extra temporary variables in a version I didn't send but I
figured they could be removed. :-)

>
> On top of that, as promised above, why not simple do it in a simpler way, i.e.
> using standard idiom:
>
> for (i = 0; i < sizeof(*fourcc); i++) {
> if (buf < end)
> *buf = tmp >> (i * 8);
> buf++;
> }
> ?

I guess that's at least more efficient, and comparing buf to end is
trivial. I'll do that in v2.

>
> > > + buf = string(buf, end, ch, spec);
> > > + }
> > > +
> > > + if (*fourcc & BIT(31))
> > > + buf = string(buf, end, "-BE", spec);
>
> Another possibility
>
> u8 ch[8];
>
> if (*fourcc & BIT(31)) {
> put_unaligned_be32(tmp, &ch[0]);
> strcpy(&ch[4], "-BE");
> } else {
> put_unaligned_le32(tmp, &ch[0]);
> strcpy(&ch[4], "-LE");
> }
> return string(buf, end, &ch[0], spec);

I think I prefer the loop. I figured you can only call string once,
otherwise field width handling will be broken. Let's see.

>
> > > + return buf;
> > > + default:
> > > + return error_string(buf, end, "(%pp?)", spec);
> > > + }
> > > +}
>

--
Kind regards,

Sakari Ailus

2020-04-06 07:39:57

by Pekka Paalanen

[permalink] [raw]
Subject: Re: [PATCH 1/1] lib/vsprintf: Add support for printing V4L2 and DRM fourccs

On Wed, 1 Apr 2020 18:13:32 +0300
Andy Shevchenko <[email protected]> wrote:

> On Wed, Apr 01, 2020 at 04:13:51PM +0200, Hans Verkuil wrote:
> > On 4/1/20 4:05 PM, Sakari Ailus wrote:
> > > Add a printk modifier %ppf (for pixel format) for printing V4L2 and DRM
> > > pixel formats denoted by 4ccs. The 4cc encoding is the same for both so
> > > the same implementation can be used.
>
> %p4cc ?
>

> Another possibility
>
> u8 ch[8];
>
> if (*fourcc & BIT(31)) {
> put_unaligned_be32(tmp, &ch[0]);
> strcpy(&ch[4], "-BE");
> } else {
> put_unaligned_le32(tmp, &ch[0]);
> strcpy(&ch[4], "-LE");
> }
> return string(buf, end, &ch[0], spec);
>

Hi,

mind, if I guess right what that code does, I think this would confuse
the fourcc code endianness and the pixel data endianness. I think fourcc
codes are always crafted machine-endian, regardless of how the pixel
data is. At least, that is what drm_fourcc.h seems to be doing with
fourcc_code(). That has nothing to do with DRM_FORMAT_BIG_ENDIAN which
refers to the pixel data.


Thanks,
pq


Attachments:
(No filename) (849.00 B)
OpenPGP digital signature