xref: /linux/drivers/gpu/drm/drm_panic_qr.rs (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: MIT
2 
3 //! This is a simple QR encoder for DRM panic.
4 //!
5 //! It is called from a panic handler, so it should't allocate memory and
6 //! does all the work on the stack or on the provided buffers. For
7 //! simplification, it only supports low error correction, and applies the
8 //! first mask (checkerboard). It will draw the smallest QRcode that can
9 //! contain the string passed as parameter. To get the most compact
10 //! QR code, the start of the URL is encoded as binary, and the
11 //! compressed kmsg is encoded as numeric.
12 //!
13 //! The binary data must be a valid URL parameter, so the easiest way is
14 //! to use base64 encoding. But this wastes 25% of data space, so the
15 //! whole stack trace won't fit in the QR code. So instead it encodes
16 //! every 13bits of input into 4 decimal digits, and then uses the
17 //! efficient numeric encoding, that encode 3 decimal digits into
18 //! 10bits. This makes 39bits of compressed data into 12 decimal digits,
19 //! into 40bits in the QR code, so wasting only 2.5%. And the numbers are
20 //! valid URL parameter, so the website can do the reverse, to get the
21 //! binary data.
22 //!
23 //! Inspired by these 3 projects, all under MIT license:
24 //!
25 //! * <https://github.com/kennytm/qrcode-rust>
26 //! * <https://github.com/erwanvivien/fast_qr>
27 //! * <https://github.com/bjguillot/qr>
28 
29 use core::cmp;
30 use kernel::str::CStr;
31 
32 #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
33 struct Version(usize);
34 
35 // Generator polynomials for ECC, only those that are needed for low quality.
36 const P7: [u8; 7] = [87, 229, 146, 149, 238, 102, 21];
37 const P10: [u8; 10] = [251, 67, 46, 61, 118, 70, 64, 94, 32, 45];
38 const P15: [u8; 15] = [
39     8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140, 124, 5, 99, 105,
40 ];
41 const P18: [u8; 18] = [
42     215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, 148, 252, 179, 5, 98, 96, 153,
43 ];
44 const P20: [u8; 20] = [
45     17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221, 225, 83, 239, 156, 164, 212, 212, 188, 190,
46 ];
47 const P22: [u8; 22] = [
48     210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200, 74, 8, 172, 98, 80, 219, 134, 160, 105,
49     165, 231,
50 ];
51 const P24: [u8; 24] = [
52     229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169, 152, 192, 226, 228, 218, 111, 0, 117,
53     232, 87, 96, 227, 21,
54 ];
55 const P26: [u8; 26] = [
56     173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111, 28, 165, 53, 161, 21, 245, 142, 13, 102,
57     48, 227, 153, 145, 218, 70,
58 ];
59 const P28: [u8; 28] = [
60     168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195, 147, 205, 27, 232, 201, 21, 43, 245, 87,
61     42, 195, 212, 119, 242, 37, 9, 123,
62 ];
63 const P30: [u8; 30] = [
64     41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110, 86, 239, 96, 222, 125, 42, 173, 226, 193,
65     224, 130, 156, 37, 251, 216, 238, 40, 192, 180,
66 ];
67 
68 /// QR Code parameters for Low quality ECC:
69 /// - Error Correction polynomial.
70 /// - Number of blocks in group 1.
71 /// - Number of blocks in group 2.
72 /// - Block size in group 1.
73 ///
74 /// (Block size in group 2 is one more than group 1).
75 struct VersionParameter(&'static [u8], u8, u8, u8);
76 const VPARAM: [VersionParameter; 40] = [
77     VersionParameter(&P7, 1, 0, 19),    // V1
78     VersionParameter(&P10, 1, 0, 34),   // V2
79     VersionParameter(&P15, 1, 0, 55),   // V3
80     VersionParameter(&P20, 1, 0, 80),   // V4
81     VersionParameter(&P26, 1, 0, 108),  // V5
82     VersionParameter(&P18, 2, 0, 68),   // V6
83     VersionParameter(&P20, 2, 0, 78),   // V7
84     VersionParameter(&P24, 2, 0, 97),   // V8
85     VersionParameter(&P30, 2, 0, 116),  // V9
86     VersionParameter(&P18, 2, 2, 68),   // V10
87     VersionParameter(&P20, 4, 0, 81),   // V11
88     VersionParameter(&P24, 2, 2, 92),   // V12
89     VersionParameter(&P26, 4, 0, 107),  // V13
90     VersionParameter(&P30, 3, 1, 115),  // V14
91     VersionParameter(&P22, 5, 1, 87),   // V15
92     VersionParameter(&P24, 5, 1, 98),   // V16
93     VersionParameter(&P28, 1, 5, 107),  // V17
94     VersionParameter(&P30, 5, 1, 120),  // V18
95     VersionParameter(&P28, 3, 4, 113),  // V19
96     VersionParameter(&P28, 3, 5, 107),  // V20
97     VersionParameter(&P28, 4, 4, 116),  // V21
98     VersionParameter(&P28, 2, 7, 111),  // V22
99     VersionParameter(&P30, 4, 5, 121),  // V23
100     VersionParameter(&P30, 6, 4, 117),  // V24
101     VersionParameter(&P26, 8, 4, 106),  // V25
102     VersionParameter(&P28, 10, 2, 114), // V26
103     VersionParameter(&P30, 8, 4, 122),  // V27
104     VersionParameter(&P30, 3, 10, 117), // V28
105     VersionParameter(&P30, 7, 7, 116),  // V29
106     VersionParameter(&P30, 5, 10, 115), // V30
107     VersionParameter(&P30, 13, 3, 115), // V31
108     VersionParameter(&P30, 17, 0, 115), // V32
109     VersionParameter(&P30, 17, 1, 115), // V33
110     VersionParameter(&P30, 13, 6, 115), // V34
111     VersionParameter(&P30, 12, 7, 121), // V35
112     VersionParameter(&P30, 6, 14, 121), // V36
113     VersionParameter(&P30, 17, 4, 122), // V37
114     VersionParameter(&P30, 4, 18, 122), // V38
115     VersionParameter(&P30, 20, 4, 117), // V39
116     VersionParameter(&P30, 19, 6, 118), // V40
117 ];
118 
119 const MAX_EC_SIZE: usize = 30;
120 const MAX_BLK_SIZE: usize = 123;
121 
122 /// Position of the alignment pattern grid.
123 const ALIGNMENT_PATTERNS: [&[u8]; 40] = [
124     &[],
125     &[6, 18],
126     &[6, 22],
127     &[6, 26],
128     &[6, 30],
129     &[6, 34],
130     &[6, 22, 38],
131     &[6, 24, 42],
132     &[6, 26, 46],
133     &[6, 28, 50],
134     &[6, 30, 54],
135     &[6, 32, 58],
136     &[6, 34, 62],
137     &[6, 26, 46, 66],
138     &[6, 26, 48, 70],
139     &[6, 26, 50, 74],
140     &[6, 30, 54, 78],
141     &[6, 30, 56, 82],
142     &[6, 30, 58, 86],
143     &[6, 34, 62, 90],
144     &[6, 28, 50, 72, 94],
145     &[6, 26, 50, 74, 98],
146     &[6, 30, 54, 78, 102],
147     &[6, 28, 54, 80, 106],
148     &[6, 32, 58, 84, 110],
149     &[6, 30, 58, 86, 114],
150     &[6, 34, 62, 90, 118],
151     &[6, 26, 50, 74, 98, 122],
152     &[6, 30, 54, 78, 102, 126],
153     &[6, 26, 52, 78, 104, 130],
154     &[6, 30, 56, 82, 108, 134],
155     &[6, 34, 60, 86, 112, 138],
156     &[6, 30, 58, 86, 114, 142],
157     &[6, 34, 62, 90, 118, 146],
158     &[6, 30, 54, 78, 102, 126, 150],
159     &[6, 24, 50, 76, 102, 128, 154],
160     &[6, 28, 54, 80, 106, 132, 158],
161     &[6, 32, 58, 84, 110, 136, 162],
162     &[6, 26, 54, 82, 110, 138, 166],
163     &[6, 30, 58, 86, 114, 142, 170],
164 ];
165 
166 /// Version information for format V7-V40.
167 const VERSION_INFORMATION: [u32; 34] = [
168     0b00_0111_1100_1001_0100,
169     0b00_1000_0101_1011_1100,
170     0b00_1001_1010_1001_1001,
171     0b00_1010_0100_1101_0011,
172     0b00_1011_1011_1111_0110,
173     0b00_1100_0111_0110_0010,
174     0b00_1101_1000_0100_0111,
175     0b00_1110_0110_0000_1101,
176     0b00_1111_1001_0010_1000,
177     0b01_0000_1011_0111_1000,
178     0b01_0001_0100_0101_1101,
179     0b01_0010_1010_0001_0111,
180     0b01_0011_0101_0011_0010,
181     0b01_0100_1001_1010_0110,
182     0b01_0101_0110_1000_0011,
183     0b01_0110_1000_1100_1001,
184     0b01_0111_0111_1110_1100,
185     0b01_1000_1110_1100_0100,
186     0b01_1001_0001_1110_0001,
187     0b01_1010_1111_1010_1011,
188     0b01_1011_0000_1000_1110,
189     0b01_1100_1100_0001_1010,
190     0b01_1101_0011_0011_1111,
191     0b01_1110_1101_0111_0101,
192     0b01_1111_0010_0101_0000,
193     0b10_0000_1001_1101_0101,
194     0b10_0001_0110_1111_0000,
195     0b10_0010_1000_1011_1010,
196     0b10_0011_0111_1001_1111,
197     0b10_0100_1011_0000_1011,
198     0b10_0101_0100_0010_1110,
199     0b10_0110_1010_0110_0100,
200     0b10_0111_0101_0100_0001,
201     0b10_1000_1100_0110_1001,
202 ];
203 
204 /// Format info for low quality ECC.
205 const FORMAT_INFOS_QR_L: [u16; 8] = [
206     0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976,
207 ];
208 
209 impl Version {
210     /// Returns the smallest QR version than can hold these segments.
211     fn from_segments(segments: &[&Segment<'_>]) -> Option<Version> {
212         for v in (1..=40).map(|k| Version(k)) {
213             if v.max_data() * 8 >= segments.iter().map(|s| s.total_size_bits(v)).sum() {
214                 return Some(v);
215             }
216         }
217         None
218     }
219 
220     fn width(&self) -> u8 {
221         (self.0 as u8) * 4 + 17
222     }
223 
224     fn max_data(&self) -> usize {
225         self.g1_blk_size() * self.g1_blocks() + (self.g1_blk_size() + 1) * self.g2_blocks()
226     }
227 
228     fn ec_size(&self) -> usize {
229         VPARAM[self.0 - 1].0.len()
230     }
231 
232     fn g1_blocks(&self) -> usize {
233         VPARAM[self.0 - 1].1 as usize
234     }
235 
236     fn g2_blocks(&self) -> usize {
237         VPARAM[self.0 - 1].2 as usize
238     }
239 
240     fn g1_blk_size(&self) -> usize {
241         VPARAM[self.0 - 1].3 as usize
242     }
243 
244     fn alignment_pattern(&self) -> &'static [u8] {
245         &ALIGNMENT_PATTERNS[self.0 - 1]
246     }
247 
248     fn poly(&self) -> &'static [u8] {
249         VPARAM[self.0 - 1].0
250     }
251 
252     fn version_info(&self) -> u32 {
253         if *self >= Version(7) {
254             VERSION_INFORMATION[self.0 - 7]
255         } else {
256             0
257         }
258     }
259 }
260 
261 /// Exponential table for Galois Field GF(256).
262 const EXP_TABLE: [u8; 256] = [
263     1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76, 152, 45, 90, 180, 117,
264     234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181,
265     119, 238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161,
266     95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187,
267     107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136,
268     13, 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197,
269     151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 168,
270     77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99, 198,
271     145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149,
272     55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167,
273     83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 18, 36, 72,
274     144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125, 250, 233, 207,
275     131, 27, 54, 108, 216, 173, 71, 142, 1,
276 ];
277 
278 /// Reverse exponential table for Galois Field GF(256).
279 const LOG_TABLE: [u8; 256] = [
280     175, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100, 224, 14, 52, 141,
281     239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142,
282     218, 240, 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114,
283     166, 6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148,
284     206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182, 163, 195, 72, 126,
285     110, 107, 58, 40, 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172,
286     115, 243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24,
287     227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149,
288     188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20, 42, 93, 158, 132,
289     60, 57, 83, 71, 109, 65, 162, 31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12,
290     111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90, 203, 89, 95,
291     176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231, 173,
292     232, 116, 214, 244, 234, 168, 80, 88, 175,
293 ];
294 
295 // 4 bits segment header.
296 const MODE_STOP: u16 = 0;
297 const MODE_NUMERIC: u16 = 1;
298 const MODE_BINARY: u16 = 4;
299 /// Padding bytes.
300 const PADDING: [u8; 2] = [236, 17];
301 
302 /// Get the next 13 bits of data, starting at specified offset (in bits).
303 fn get_next_13b(data: &[u8], offset: usize) -> Option<(u16, usize)> {
304     if offset < data.len() * 8 {
305         let size = cmp::min(13, data.len() * 8 - offset);
306         let byte_off = offset / 8;
307         let bit_off = offset % 8;
308         // `b` is 20 at max (`bit_off` <= 7 and `size` <= 13).
309         let b = (bit_off + size) as u16;
310 
311         let first_byte = (data[byte_off] << bit_off >> bit_off) as u16;
312 
313         let number = match b {
314             0..=8 => first_byte >> (8 - b),
315             9..=16 => (first_byte << (b - 8)) + (data[byte_off + 1] >> (16 - b)) as u16,
316             _ => {
317                 (first_byte << (b - 8))
318                     + ((data[byte_off + 1] as u16) << (b - 16))
319                     + (data[byte_off + 2] >> (24 - b)) as u16
320             }
321         };
322         Some((number, size))
323     } else {
324         None
325     }
326 }
327 
328 /// Number of bits to encode characters in numeric mode.
329 const NUM_CHARS_BITS: [usize; 4] = [0, 4, 7, 10];
330 const POW10: [u16; 4] = [1, 10, 100, 1000];
331 
332 enum Segment<'a> {
333     Numeric(&'a [u8]),
334     Binary(&'a [u8]),
335 }
336 
337 impl Segment<'_> {
338     fn get_header(&self) -> (u16, usize) {
339         match self {
340             Segment::Binary(_) => (MODE_BINARY, 4),
341             Segment::Numeric(_) => (MODE_NUMERIC, 4),
342         }
343     }
344 
345     // Returns the size of the length field in bits, depending on QR Version.
346     fn length_bits_count(&self, version: Version) -> usize {
347         let Version(v) = version;
348         match self {
349             Segment::Binary(_) => match v {
350                 1..=9 => 8,
351                 _ => 16,
352             },
353             Segment::Numeric(_) => match v {
354                 1..=9 => 10,
355                 10..=26 => 12,
356                 _ => 14,
357             },
358         }
359     }
360 
361     // Number of characters in the segment.
362     fn character_count(&self) -> usize {
363         match self {
364             Segment::Binary(data) => data.len(),
365             Segment::Numeric(data) => {
366                 let data_bits = data.len() * 8;
367                 let last_chars = match data_bits % 13 {
368                     1 => 1,
369                     k => (k + 1) / 3,
370                 };
371                 // 4 decimal numbers per 13bits + remainder.
372                 4 * (data_bits / 13) + last_chars
373             }
374         }
375     }
376 
377     fn get_length_field(&self, version: Version) -> (u16, usize) {
378         (
379             self.character_count() as u16,
380             self.length_bits_count(version),
381         )
382     }
383 
384     fn total_size_bits(&self, version: Version) -> usize {
385         let data_size = match self {
386             Segment::Binary(data) => data.len() * 8,
387             Segment::Numeric(_) => {
388                 let digits = self.character_count();
389                 10 * (digits / 3) + NUM_CHARS_BITS[digits % 3]
390             }
391         };
392         // header + length + data.
393         4 + self.length_bits_count(version) + data_size
394     }
395 
396     fn iter(&self) -> SegmentIterator<'_> {
397         SegmentIterator {
398             segment: self,
399             offset: 0,
400             carry: 0,
401             carry_len: 0,
402         }
403     }
404 }
405 
406 struct SegmentIterator<'a> {
407     segment: &'a Segment<'a>,
408     offset: usize,
409     carry: u16,
410     carry_len: usize,
411 }
412 
413 impl Iterator for SegmentIterator<'_> {
414     type Item = (u16, usize);
415 
416     fn next(&mut self) -> Option<Self::Item> {
417         match self.segment {
418             Segment::Binary(data) => {
419                 if self.offset < data.len() {
420                     let byte = data[self.offset] as u16;
421                     self.offset += 1;
422                     Some((byte, 8))
423                 } else {
424                     None
425                 }
426             }
427             Segment::Numeric(data) => {
428                 if self.carry_len == 3 {
429                     let out = (self.carry, NUM_CHARS_BITS[self.carry_len]);
430                     self.carry_len = 0;
431                     self.carry = 0;
432                     Some(out)
433                 } else if let Some((bits, size)) = get_next_13b(data, self.offset) {
434                     self.offset += size;
435                     let new_chars = match size {
436                         1 => 1,
437                         k => (k + 1) / 3,
438                     };
439                     if self.carry_len + new_chars > 3 {
440                         self.carry_len = new_chars + self.carry_len - 3;
441                         let out = (
442                             self.carry * POW10[new_chars - self.carry_len]
443                                 + bits / POW10[self.carry_len],
444                             NUM_CHARS_BITS[3],
445                         );
446                         self.carry = bits % POW10[self.carry_len];
447                         Some(out)
448                     } else {
449                         let out = (
450                             self.carry * POW10[new_chars] + bits,
451                             NUM_CHARS_BITS[self.carry_len + new_chars],
452                         );
453                         self.carry_len = 0;
454                         Some(out)
455                     }
456                 } else if self.carry_len > 0 {
457                     let out = (self.carry, NUM_CHARS_BITS[self.carry_len]);
458                     self.carry_len = 0;
459                     Some(out)
460                 } else {
461                     None
462                 }
463             }
464         }
465     }
466 }
467 
468 struct EncodedMsg<'a> {
469     data: &'a mut [u8],
470     ec_size: usize,
471     g1_blocks: usize,
472     g2_blocks: usize,
473     g1_blk_size: usize,
474     g2_blk_size: usize,
475     poly: &'static [u8],
476     version: Version,
477 }
478 
479 /// Data to be put in the QR code, with correct segment encoding, padding, and
480 /// Error Code Correction.
481 impl EncodedMsg<'_> {
482     fn new<'a, 'b>(segments: &[&Segment<'b>], data: &'a mut [u8]) -> Option<EncodedMsg<'a>> {
483         let version = Version::from_segments(segments)?;
484         let ec_size = version.ec_size();
485         let g1_blocks = version.g1_blocks();
486         let g2_blocks = version.g2_blocks();
487         let g1_blk_size = version.g1_blk_size();
488         let g2_blk_size = g1_blk_size + 1;
489         let poly = version.poly();
490 
491         // clear the output.
492         data.fill(0);
493 
494         let mut em = EncodedMsg {
495             data: data,
496             ec_size,
497             g1_blocks,
498             g2_blocks,
499             g1_blk_size,
500             g2_blk_size,
501             poly,
502             version,
503         };
504         em.encode(segments);
505         Some(em)
506     }
507 
508     /// Push bits of data at an offset (in bits).
509     fn push(&mut self, offset: &mut usize, bits: (u16, usize)) {
510         let (number, len_bits) = bits;
511         let byte_off = *offset / 8;
512         let bit_off = *offset % 8;
513         let b = bit_off + len_bits;
514 
515         match (bit_off, b) {
516             (0, 0..=8) => {
517                 self.data[byte_off] = (number << (8 - b)) as u8;
518             }
519             (0, _) => {
520                 self.data[byte_off] = (number >> (b - 8)) as u8;
521                 self.data[byte_off + 1] = (number << (16 - b)) as u8;
522             }
523             (_, 0..=8) => {
524                 self.data[byte_off] |= (number << (8 - b)) as u8;
525             }
526             (_, 9..=16) => {
527                 self.data[byte_off] |= (number >> (b - 8)) as u8;
528                 self.data[byte_off + 1] = (number << (16 - b)) as u8;
529             }
530             _ => {
531                 self.data[byte_off] |= (number >> (b - 8)) as u8;
532                 self.data[byte_off + 1] = (number >> (b - 16)) as u8;
533                 self.data[byte_off + 2] = (number << (24 - b)) as u8;
534             }
535         }
536         *offset += len_bits;
537     }
538 
539     fn add_segments(&mut self, segments: &[&Segment<'_>]) {
540         let mut offset: usize = 0;
541 
542         for s in segments.iter() {
543             self.push(&mut offset, s.get_header());
544             self.push(&mut offset, s.get_length_field(self.version));
545             for bits in s.iter() {
546                 self.push(&mut offset, bits);
547             }
548         }
549         self.push(&mut offset, (MODE_STOP, 4));
550 
551         let pad_offset = (offset + 7) / 8;
552         for i in pad_offset..self.version.max_data() {
553             self.data[i] = PADDING[(i & 1) ^ (pad_offset & 1)];
554         }
555     }
556 
557     fn error_code_for_blocks(&mut self, offset: usize, size: usize, ec_offset: usize) {
558         let mut tmp: [u8; MAX_BLK_SIZE + MAX_EC_SIZE] = [0; MAX_BLK_SIZE + MAX_EC_SIZE];
559 
560         tmp[0..size].copy_from_slice(&self.data[offset..offset + size]);
561         for i in 0..size {
562             let lead_coeff = tmp[i] as usize;
563             if lead_coeff == 0 {
564                 continue;
565             }
566             let log_lead_coeff = usize::from(LOG_TABLE[lead_coeff]);
567             for (u, &v) in tmp[i + 1..].iter_mut().zip(self.poly.iter()) {
568                 *u ^= EXP_TABLE[(usize::from(v) + log_lead_coeff) % 255];
569             }
570         }
571         self.data[ec_offset..ec_offset + self.ec_size]
572             .copy_from_slice(&tmp[size..size + self.ec_size]);
573     }
574 
575     fn compute_error_code(&mut self) {
576         let mut offset = 0;
577         let mut ec_offset = self.g1_blocks * self.g1_blk_size + self.g2_blocks * self.g2_blk_size;
578 
579         for _ in 0..self.g1_blocks {
580             self.error_code_for_blocks(offset, self.g1_blk_size, ec_offset);
581             offset += self.g1_blk_size;
582             ec_offset += self.ec_size;
583         }
584         for _ in 0..self.g2_blocks {
585             self.error_code_for_blocks(offset, self.g2_blk_size, ec_offset);
586             offset += self.g2_blk_size;
587             ec_offset += self.ec_size;
588         }
589     }
590 
591     fn encode(&mut self, segments: &[&Segment<'_>]) {
592         self.add_segments(segments);
593         self.compute_error_code();
594     }
595 
596     fn iter(&self) -> EncodedMsgIterator<'_> {
597         EncodedMsgIterator {
598             em: self,
599             offset: 0,
600         }
601     }
602 }
603 
604 /// Iterator, to retrieve the data in the interleaved order needed by QR code.
605 struct EncodedMsgIterator<'a> {
606     em: &'a EncodedMsg<'a>,
607     offset: usize,
608 }
609 
610 impl Iterator for EncodedMsgIterator<'_> {
611     type Item = u8;
612 
613     // Send the bytes in interleaved mode, first byte of first block of group1,
614     // then first byte of second block of group1, ...
615     fn next(&mut self) -> Option<Self::Item> {
616         let em = self.em;
617         let blocks = em.g1_blocks + em.g2_blocks;
618         let g1_end = em.g1_blocks * em.g1_blk_size;
619         let g2_end = g1_end + em.g2_blocks * em.g2_blk_size;
620         let ec_end = g2_end + em.ec_size * blocks;
621 
622         if self.offset >= ec_end {
623             return None;
624         }
625 
626         let offset = if self.offset < em.g1_blk_size * blocks {
627             // group1 and group2 interleaved
628             let blk = self.offset % blocks;
629             let blk_off = self.offset / blocks;
630             if blk < em.g1_blocks {
631                 blk * em.g1_blk_size + blk_off
632             } else {
633                 g1_end + em.g2_blk_size * (blk - em.g1_blocks) + blk_off
634             }
635         } else if self.offset < g2_end {
636             // last byte of group2 blocks
637             let blk2 = self.offset - blocks * em.g1_blk_size;
638             em.g1_blk_size * em.g1_blocks + blk2 * em.g2_blk_size + em.g2_blk_size - 1
639         } else {
640             // EC blocks
641             let ec_offset = self.offset - g2_end;
642             let blk = ec_offset % blocks;
643             let blk_off = ec_offset / blocks;
644 
645             g2_end + blk * em.ec_size + blk_off
646         };
647         self.offset += 1;
648         Some(em.data[offset])
649     }
650 }
651 
652 /// A QR code image, encoded as a linear binary framebuffer.
653 /// 1 bit per module (pixel), each new line start at next byte boundary.
654 /// Max width is 177 for V40 QR code, so `u8` is enough for coordinate.
655 struct QrImage<'a> {
656     data: &'a mut [u8],
657     width: u8,
658     stride: u8,
659     version: Version,
660 }
661 
662 impl QrImage<'_> {
663     fn new<'a, 'b>(em: &'b EncodedMsg<'b>, qrdata: &'a mut [u8]) -> QrImage<'a> {
664         let width = em.version.width();
665         let stride = (width + 7) / 8;
666         let data = qrdata;
667 
668         let mut qr_image = QrImage {
669             data,
670             width,
671             stride,
672             version: em.version,
673         };
674         qr_image.draw_all(em.iter());
675         qr_image
676     }
677 
678     fn clear(&mut self) {
679         self.data.fill(0);
680     }
681 
682     // Set pixel to light color.
683     fn set(&mut self, x: u8, y: u8) {
684         let off = y as usize * self.stride as usize + x as usize / 8;
685         let mut v = self.data[off];
686         v |= 0x80 >> (x % 8);
687         self.data[off] = v;
688     }
689 
690     // Invert a module color.
691     fn xor(&mut self, x: u8, y: u8) {
692         let off = y as usize * self.stride as usize + x as usize / 8;
693         self.data[off] ^= 0x80 >> (x % 8);
694     }
695 
696     // Draw a light square at (x, y) top left corner.
697     fn draw_square(&mut self, x: u8, y: u8, size: u8) {
698         for k in 0..size {
699             self.set(x + k, y);
700             self.set(x, y + k + 1);
701             self.set(x + size, y + k);
702             self.set(x + k + 1, y + size);
703         }
704     }
705 
706     // Finder pattern: 3 8x8 square at the corners.
707     fn draw_finders(&mut self) {
708         self.draw_square(1, 1, 4);
709         self.draw_square(self.width - 6, 1, 4);
710         self.draw_square(1, self.width - 6, 4);
711         for k in 0..8 {
712             self.set(k, 7);
713             self.set(self.width - k - 1, 7);
714             self.set(k, self.width - 8);
715         }
716         for k in 0..7 {
717             self.set(7, k);
718             self.set(self.width - 8, k);
719             self.set(7, self.width - 1 - k);
720         }
721     }
722 
723     fn is_finder(&self, x: u8, y: u8) -> bool {
724         let end = self.width - 8;
725         (x < 8 && y < 8) || (x < 8 && y >= end) || (x >= end && y < 8)
726     }
727 
728     // Alignment pattern: 5x5 squares in a grid.
729     fn draw_alignments(&mut self) {
730         let positions = self.version.alignment_pattern();
731         for &x in positions.iter() {
732             for &y in positions.iter() {
733                 if !self.is_finder(x, y) {
734                     self.draw_square(x - 1, y - 1, 2);
735                 }
736             }
737         }
738     }
739 
740     fn is_alignment(&self, x: u8, y: u8) -> bool {
741         let positions = self.version.alignment_pattern();
742         for &ax in positions.iter() {
743             for &ay in positions.iter() {
744                 if self.is_finder(ax, ay) {
745                     continue;
746                 }
747                 if x >= ax - 2 && x <= ax + 2 && y >= ay - 2 && y <= ay + 2 {
748                     return true;
749                 }
750             }
751         }
752         false
753     }
754 
755     // Timing pattern: 2 dotted line between the finder patterns.
756     fn draw_timing_patterns(&mut self) {
757         let end = self.width - 8;
758 
759         for x in (9..end).step_by(2) {
760             self.set(x, 6);
761             self.set(6, x);
762         }
763     }
764 
765     fn is_timing(&self, x: u8, y: u8) -> bool {
766         x == 6 || y == 6
767     }
768 
769     // Mask info: 15 bits around the finders, written twice for redundancy.
770     fn draw_maskinfo(&mut self) {
771         let info: u16 = FORMAT_INFOS_QR_L[0];
772         let mut skip = 0;
773 
774         for k in 0..7 {
775             if k == 6 {
776                 skip = 1;
777             }
778             if info & (1 << (14 - k)) == 0 {
779                 self.set(k + skip, 8);
780                 self.set(8, self.width - 1 - k);
781             }
782         }
783         skip = 0;
784         for k in 0..8 {
785             if k == 2 {
786                 skip = 1;
787             }
788             if info & (1 << (7 - k)) == 0 {
789                 self.set(8, 8 - skip - k);
790                 self.set(self.width - 8 + k, 8);
791             }
792         }
793     }
794 
795     fn is_maskinfo(&self, x: u8, y: u8) -> bool {
796         let end = self.width - 8;
797         // Count the dark module as mask info.
798         (x <= 8 && y == 8) || (y <= 8 && x == 8) || (x == 8 && y >= end) || (x >= end && y == 8)
799     }
800 
801     // Version info: 18bits written twice, close to the finders.
802     fn draw_version_info(&mut self) {
803         let vinfo = self.version.version_info();
804         let pos = self.width - 11;
805 
806         if vinfo != 0 {
807             for x in 0..3 {
808                 for y in 0..6 {
809                     if vinfo & (1 << (x + y * 3)) == 0 {
810                         self.set(x + pos, y);
811                         self.set(y, x + pos);
812                     }
813                 }
814             }
815         }
816     }
817 
818     fn is_version_info(&self, x: u8, y: u8) -> bool {
819         let vinfo = self.version.version_info();
820         let pos = self.width - 11;
821 
822         vinfo != 0 && ((x >= pos && x < pos + 3 && y < 6) || (y >= pos && y < pos + 3 && x < 6))
823     }
824 
825     // Returns true if the module is reserved (Not usable for data and EC).
826     fn is_reserved(&self, x: u8, y: u8) -> bool {
827         self.is_alignment(x, y)
828             || self.is_finder(x, y)
829             || self.is_timing(x, y)
830             || self.is_maskinfo(x, y)
831             || self.is_version_info(x, y)
832     }
833 
834     // Last module to draw, at bottom left corner.
835     fn is_last(&self, x: u8, y: u8) -> bool {
836         x == 0 && y == self.width - 1
837     }
838 
839     // Move to the next module according to QR code order.
840     // From bottom right corner, to bottom left corner.
841     fn next(&self, x: u8, y: u8) -> (u8, u8) {
842         let x_adj = if x <= 6 { x + 1 } else { x };
843         let column_type = (self.width - x_adj) % 4;
844 
845         match column_type {
846             2 if y > 0 => (x + 1, y - 1),
847             0 if y < self.width - 1 => (x + 1, y + 1),
848             0 | 2 if x == 7 => (x - 2, y),
849             _ => (x - 1, y),
850         }
851     }
852 
853     // Find next module that can hold data.
854     fn next_available(&self, x: u8, y: u8) -> (u8, u8) {
855         let (mut x, mut y) = self.next(x, y);
856         while self.is_reserved(x, y) && !self.is_last(x, y) {
857             (x, y) = self.next(x, y);
858         }
859         (x, y)
860     }
861 
862     fn draw_data(&mut self, data: impl Iterator<Item = u8>) {
863         let (mut x, mut y) = (self.width - 1, self.width - 1);
864         for byte in data {
865             for s in 0..8 {
866                 if byte & (0x80 >> s) == 0 {
867                     self.set(x, y);
868                 }
869                 (x, y) = self.next_available(x, y);
870             }
871         }
872         // Set the remaining modules (0, 3 or 7 depending on version).
873         // because 0 correspond to a light module.
874         while !self.is_last(x, y) {
875             if !self.is_reserved(x, y) {
876                 self.set(x, y);
877             }
878             (x, y) = self.next(x, y);
879         }
880     }
881 
882     // Apply checkerboard mask to all non-reserved modules.
883     fn apply_mask(&mut self) {
884         for x in 0..self.width {
885             for y in 0..self.width {
886                 if (x ^ y) % 2 == 0 && !self.is_reserved(x, y) {
887                     self.xor(x, y);
888                 }
889             }
890         }
891     }
892 
893     // Draw the QR code with the provided data iterator.
894     fn draw_all(&mut self, data: impl Iterator<Item = u8>) {
895         // First clear the table, as it may have already some data.
896         self.clear();
897         self.draw_finders();
898         self.draw_alignments();
899         self.draw_timing_patterns();
900         self.draw_version_info();
901         self.draw_data(data);
902         self.draw_maskinfo();
903         self.apply_mask();
904     }
905 }
906 
907 /// C entry point for the rust QR Code generator.
908 ///
909 /// Write the QR code image in the data buffer, and return the QR code width,
910 /// or 0, if the data doesn't fit in a QR code.
911 ///
912 /// * `url`: The base URL of the QR code. It will be encoded as Binary segment.
913 /// * `data`: A pointer to the binary data, to be encoded. if URL is NULL, it
914 ///    will be encoded as binary segment, otherwise it will be encoded
915 ///    efficiently as a numeric segment, and appended to the URL.
916 /// * `data_len`: Length of the data, that needs to be encoded, must be less
917 ///    than data_size.
918 /// * `data_size`: Size of data buffer, it should be at least 4071 bytes to hold
919 ///    a V40 QR code. It will then be overwritten with the QR code image.
920 /// * `tmp`: A temporary buffer that the QR code encoder will use, to write the
921 ///    segments and ECC.
922 /// * `tmp_size`: Size of the temporary buffer, it must be at least 3706 bytes
923 ///    long for V40.
924 ///
925 /// # Safety
926 ///
927 /// * `url` must be null or point at a nul-terminated string.
928 /// * `data` must be valid for reading and writing for `data_size` bytes.
929 /// * `tmp` must be valid for reading and writing for `tmp_size` bytes.
930 ///
931 /// They must remain valid for the duration of the function call.
932 
933 #[no_mangle]
934 pub unsafe extern "C" fn drm_panic_qr_generate(
935     url: *const i8,
936     data: *mut u8,
937     data_len: usize,
938     data_size: usize,
939     tmp: *mut u8,
940     tmp_size: usize,
941 ) -> u8 {
942     if data_size < 4071 || tmp_size < 3706 || data_len > data_size {
943         return 0;
944     }
945     // SAFETY: The caller ensures that `data` is a valid pointer for reading and
946     // writing `data_size` bytes.
947     let data_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(data, data_size) };
948     // SAFETY: The caller ensures that `tmp` is a valid pointer for reading and
949     // writing `tmp_size` bytes.
950     let tmp_slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(tmp, tmp_size) };
951     if url.is_null() {
952         match EncodedMsg::new(&[&Segment::Binary(&data_slice[0..data_len])], tmp_slice) {
953             None => 0,
954             Some(em) => {
955                 let qr_image = QrImage::new(&em, data_slice);
956                 qr_image.width
957             }
958         }
959     } else {
960         // SAFETY: The caller ensures that `url` is a valid pointer to a
961         // nul-terminated string.
962         let url_cstr: &CStr = unsafe { CStr::from_char_ptr(url) };
963         let segments = &[
964             &Segment::Binary(url_cstr.as_bytes()),
965             &Segment::Numeric(&data_slice[0..data_len]),
966         ];
967         match EncodedMsg::new(segments, tmp_slice) {
968             None => 0,
969             Some(em) => {
970                 let qr_image = QrImage::new(&em, data_slice);
971                 qr_image.width
972             }
973         }
974     }
975 }
976 
977 /// Returns the maximum data size that can fit in a QR code of this version.
978 /// * `version`: QR code version, between 1-40.
979 /// * `url_len`: Length of the URL.
980 ///
981 /// * If `url_len` > 0, remove the 2 segments header/length and also count the
982 /// conversion to numeric segments.
983 /// * If `url_len` = 0, only removes 3 bytes for 1 binary segment.
984 #[no_mangle]
985 pub extern "C" fn drm_panic_qr_max_data_size(version: u8, url_len: usize) -> usize {
986     if version < 1 || version > 40 {
987         return 0;
988     }
989     let max_data = Version(version as usize).max_data();
990 
991     if url_len > 0 {
992         // Binary segment (URL) 4 + 16 bits, numeric segment (kmsg) 4 + 12 bits => 5 bytes.
993         if url_len + 5 >= max_data {
994             0
995         } else {
996             let max = max_data - url_len - 5;
997             (max * 39) / 40
998         }
999     } else {
1000         // Remove 3 bytes for the binary segment (header 4 bits, length 16 bits, stop 4bits).
1001         max_data - 3
1002     }
1003 }
1004