-
Notifications
You must be signed in to change notification settings - Fork 12
/
1012-lib-vsprintf-Add-support-for-generic-FOURCCs-by-exte.patch
197 lines (180 loc) · 6.14 KB
/
1012-lib-vsprintf-Add-support-for-generic-FOURCCs-by-exte.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
From f6ab7e4580962c9d82e7dc40dd074d47b2bce034 Mon Sep 17 00:00:00 2001
From: Hector Martin <[email protected]>
Date: Tue, 1 Feb 2022 00:40:51 +0900
Subject: [PATCH 09/12] lib/vsprintf: Add support for generic FOURCCs by
extending %p4cc
%p4cc is designed for DRM/V4L2 FOURCCs with their specific quirks, but
it's useful to be able to print generic 4-character codes formatted as
an integer. Extend it to add format specifiers for printing generic
32-bit FOURCCs with various endian semantics:
%p4ch Host-endian
%p4cl Little-endian
%p4cb Big-endian
%p4cr Reverse-endian
The endianness determines how bytes are interpreted as a u32, and the
FOURCC is then always printed MSByte-first (this is the opposite of
V4L/DRM FOURCCs). This covers most practical cases, e.g. %p4cr would
allow printing LSByte-first FOURCCs stored in host endian order
(other than the hex form being in character order, not the integer
value).
Signed-off-by: Hector Martin <[email protected]>
Signed-off-by: Kerem Karabay <[email protected]>
---
Documentation/core-api/printk-formats.rst | 32 ++++++++++++++++++++
lib/test_printf.c | 20 +++++++++----
lib/vsprintf.c | 36 +++++++++++++++++++----
scripts/checkpatch.pl | 2 +-
4 files changed, 77 insertions(+), 13 deletions(-)
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index dfe7e75a7..0ccef63e6 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -631,6 +631,38 @@ Examples::
%p4cc Y10 little-endian (0x20303159)
%p4cc NV12 big-endian (0xb231564e)
+Generic FourCC code
+-------------------
+
+::
+ %p4c[hnbl] gP00 (0x67503030)
+
+Print a generic FourCC code, as both ASCII characters and its numerical
+value as hexadecimal.
+
+The additional ``h``, ``r``, ``b``, and ``l`` specifiers are used to specify
+host, reversed, big or little endian order data respectively. Host endian
+order means the data is interpreted as a 32-bit integer and the most
+significant byte is printed first; that is, the character code as printed
+matches the byte order stored in memory on big-endian systems, and is reversed
+on little-endian systems.
+
+Passed by reference.
+
+Examples for a little-endian machine, given &(u32)0x67503030::
+
+ %p4ch gP00 (0x67503030)
+ %p4cl gP00 (0x67503030)
+ %p4cb 00Pg (0x30305067)
+ %p4cr 00Pg (0x30305067)
+
+Examples for a big-endian machine, given &(u32)0x67503030::
+
+ %p4ch gP00 (0x67503030)
+ %p4cl 00Pg (0x30305067)
+ %p4cb gP00 (0x67503030)
+ %p4cr 00Pg (0x30305067)
+
Rust
----
diff --git a/lib/test_printf.c b/lib/test_printf.c
index 7677ebccf..2355be36f 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -746,18 +746,26 @@ static void __init fwnode_pointer(void)
static void __init fourcc_pointer(void)
{
struct {
+ char type;
u32 code;
char *str;
} const try[] = {
- { 0x3231564e, "NV12 little-endian (0x3231564e)", },
- { 0xb231564e, "NV12 big-endian (0xb231564e)", },
- { 0x10111213, ".... little-endian (0x10111213)", },
- { 0x20303159, "Y10 little-endian (0x20303159)", },
+ { 'c', 0x3231564e, "NV12 little-endian (0x3231564e)", },
+ { 'c', 0xb231564e, "NV12 big-endian (0xb231564e)", },
+ { 'c', 0x10111213, ".... little-endian (0x10111213)", },
+ { 'c', 0x20303159, "Y10 little-endian (0x20303159)", },
+ { 'h', 0x67503030, "gP00 (0x67503030)", },
+ { 'r', 0x30305067, "gP00 (0x67503030)", },
+ { 'l', cpu_to_le32(0x67503030), "gP00 (0x67503030)", },
+ { 'b', cpu_to_be32(0x67503030), "gP00 (0x67503030)", },
};
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(try); i++)
- test(try[i].str, "%p4cc", &try[i].code);
+ for (i = 0; i < ARRAY_SIZE(try); i++) {
+ char fmt[] = { '%', 'p', '4', 'c', try[i].type, '\0' };
+
+ test(try[i].str, fmt, &try[i].code);
+ }
}
static void __init
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 40f560959..bd9af783c 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1758,27 +1758,50 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
char output[sizeof("0123 little-endian (0x01234567)")];
char *p = output;
unsigned int i;
+ bool pix_fmt = false;
u32 orig, val;
- if (fmt[1] != 'c' || fmt[2] != 'c')
+ if (fmt[1] != 'c')
return error_string(buf, end, "(%p4?)", spec);
if (check_pointer(&buf, end, fourcc, spec))
return buf;
orig = get_unaligned(fourcc);
- val = orig & ~BIT(31);
+ switch (fmt[2]) {
+ case 'h':
+ val = orig;
+ break;
+ case 'r':
+ val = orig = swab32(orig);
+ break;
+ case 'l':
+ val = orig = le32_to_cpu(orig);
+ break;
+ case 'b':
+ val = orig = be32_to_cpu(orig);
+ break;
+ case 'c':
+ /* Pixel formats are printed LSB-first */
+ val = swab32(orig & ~BIT(31));
+ pix_fmt = true;
+ break;
+ default:
+ return error_string(buf, end, "(%p4?)", spec);
+ }
for (i = 0; i < sizeof(u32); i++) {
- unsigned char c = val >> (i * 8);
+ unsigned char c = val >> ((3 - i) * 8);
/* Print non-control ASCII characters as-is, dot otherwise */
*p++ = isascii(c) && isprint(c) ? c : '.';
}
- *p++ = ' ';
- strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian");
- p += strlen(p);
+ if (pix_fmt) {
+ *p++ = ' ';
+ strcpy(p, orig & BIT(31) ? "big-endian" : "little-endian");
+ p += strlen(p);
+ }
*p++ = ' ';
*p++ = '(';
@@ -2348,6 +2371,7 @@ char *rust_fmt_argument(char *buf, char *end, void *ptr);
* read the documentation (path below) first.
* - 'NF' For a netdev_features_t
* - '4cc' V4L2 or DRM FourCC code, with endianness and raw numerical value.
+ * - '4c[hlbr]' Generic FourCC code.
* - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
* a certain separator (' ' by default):
* C colon
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 880fde13d..f080e33a4 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6906,7 +6906,7 @@ sub process {
($extension eq "f" &&
defined $qualifier && $qualifier !~ /^w/) ||
($extension eq "4" &&
- defined $qualifier && $qualifier !~ /^cc/)) {
+ defined $qualifier && $qualifier !~ /^c[chlbr]/)) {
$bad_specifier = $specifier;
last;
}
--
2.42.0