Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016-2018 NXP
3 * Copyright (c) 2018-2019, Vladimir Oltean <olteanv@gmail.com>
4 */
5#ifndef _LINUX_PACKING_H
6#define _LINUX_PACKING_H
7
8#include <linux/types.h>
9#include <linux/bitops.h>
10
11#define GEN_PACKED_FIELD_STRUCT(__type) \
12 struct packed_field_ ## __type { \
13 __type startbit; \
14 __type endbit; \
15 __type offset; \
16 __type size; \
17 }
18
19/* struct packed_field_u8. Use with bit offsets < 256, buffers < 32B and
20 * unpacked structures < 256B.
21 */
22GEN_PACKED_FIELD_STRUCT(u8);
23
24/* struct packed_field_u16. Use with bit offsets < 65536, buffers < 8KB and
25 * unpacked structures < 64KB.
26 */
27GEN_PACKED_FIELD_STRUCT(u16);
28
29#define PACKED_FIELD(start, end, struct_name, struct_field) \
30{ \
31 (start), \
32 (end), \
33 offsetof(struct_name, struct_field), \
34 sizeof_field(struct_name, struct_field), \
35}
36
37#define CHECK_PACKED_FIELD_OVERLAP(fields, index1, index2) ({ \
38 typeof(&(fields)[0]) __f = (fields); \
39 typeof(__f[0]) _f1 = __f[index1]; typeof(__f[0]) _f2 = __f[index2]; \
40 const bool _ascending = __f[0].startbit < __f[1].startbit; \
41 BUILD_BUG_ON_MSG(_ascending && _f1.startbit >= _f2.startbit, \
42 __stringify(fields) " field " __stringify(index2) \
43 " breaks ascending order"); \
44 BUILD_BUG_ON_MSG(!_ascending && _f1.startbit <= _f2.startbit, \
45 __stringify(fields) " field " __stringify(index2) \
46 " breaks descending order"); \
47 BUILD_BUG_ON_MSG(max(_f1.endbit, _f2.endbit) <= \
48 min(_f1.startbit, _f2.startbit), \
49 __stringify(fields) " field " __stringify(index2) \
50 " overlaps with previous field"); \
51})
52
53#define CHECK_PACKED_FIELD(fields, index) ({ \
54 typeof(&(fields)[0]) _f = (fields); \
55 typeof(_f[0]) __f = _f[index]; \
56 BUILD_BUG_ON_MSG(__f.startbit < __f.endbit, \
57 __stringify(fields) " field " __stringify(index) \
58 " start bit must not be smaller than end bit"); \
59 BUILD_BUG_ON_MSG(__f.size != 1 && __f.size != 2 && \
60 __f.size != 4 && __f.size != 8, \
61 __stringify(fields) " field " __stringify(index) \
62 " has unsupported unpacked storage size"); \
63 BUILD_BUG_ON_MSG(__f.startbit - __f.endbit >= BITS_PER_BYTE * __f.size, \
64 __stringify(fields) " field " __stringify(index) \
65 " exceeds unpacked storage size"); \
66 __builtin_choose_expr(index != 0, \
67 CHECK_PACKED_FIELD_OVERLAP(fields, index - 1, index), \
68 1); \
69})
70
71/* Note that the packed fields may be either in ascending or descending order.
72 * Thus, we must check that both the first and last field wit within the
73 * packed buffer size.
74 */
75#define CHECK_PACKED_FIELDS_SIZE(fields, pbuflen) ({ \
76 typeof(&(fields)[0]) _f = (fields); \
77 typeof(pbuflen) _len = (pbuflen); \
78 const size_t num_fields = ARRAY_SIZE(fields); \
79 BUILD_BUG_ON_MSG(!__builtin_constant_p(_len), \
80 __stringify(fields) " pbuflen " __stringify(pbuflen) \
81 " must be a compile time constant"); \
82 BUILD_BUG_ON_MSG(_f[0].startbit >= BITS_PER_BYTE * _len, \
83 __stringify(fields) " first field exceeds packed buffer size"); \
84 BUILD_BUG_ON_MSG(_f[num_fields - 1].startbit >= BITS_PER_BYTE * _len, \
85 __stringify(fields) " last field exceeds packed buffer size"); \
86})
87
88#define QUIRK_MSB_ON_THE_RIGHT BIT(0)
89#define QUIRK_LITTLE_ENDIAN BIT(1)
90#define QUIRK_LSW32_IS_FIRST BIT(2)
91
92enum packing_op {
93 PACK,
94 UNPACK,
95};
96
97int packing(void *pbuf, u64 *uval, int startbit, int endbit, size_t pbuflen,
98 enum packing_op op, u8 quirks);
99
100int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
101 u8 quirks);
102
103int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
104 size_t pbuflen, u8 quirks);
105
106void pack_fields_u8(void *pbuf, size_t pbuflen, const void *ustruct,
107 const struct packed_field_u8 *fields, size_t num_fields,
108 u8 quirks);
109
110void pack_fields_u16(void *pbuf, size_t pbuflen, const void *ustruct,
111 const struct packed_field_u16 *fields, size_t num_fields,
112 u8 quirks);
113
114void unpack_fields_u8(const void *pbuf, size_t pbuflen, void *ustruct,
115 const struct packed_field_u8 *fields, size_t num_fields,
116 u8 quirks);
117
118void unpack_fields_u16(const void *pbuf, size_t pbuflen, void *ustruct,
119 const struct packed_field_u16 *fields, size_t num_fields,
120 u8 quirks);
121
122/* Do not hand-edit the following packed field check macros!
123 *
124 * They are generated using scripts/gen_packed_field_checks.c, which may be
125 * built via "make scripts_gen_packed_field_checks". If larger macro sizes are
126 * needed in the future, please use this program to re-generate the macros and
127 * insert them here.
128 */
129
130#define CHECK_PACKED_FIELDS_1(fields) \
131 CHECK_PACKED_FIELD(fields, 0)
132
133#define CHECK_PACKED_FIELDS_2(fields) do { \
134 CHECK_PACKED_FIELDS_1(fields); \
135 CHECK_PACKED_FIELD(fields, 1); \
136} while (0)
137
138#define CHECK_PACKED_FIELDS_3(fields) do { \
139 CHECK_PACKED_FIELDS_2(fields); \
140 CHECK_PACKED_FIELD(fields, 2); \
141} while (0)
142
143#define CHECK_PACKED_FIELDS_4(fields) do { \
144 CHECK_PACKED_FIELDS_3(fields); \
145 CHECK_PACKED_FIELD(fields, 3); \
146} while (0)
147
148#define CHECK_PACKED_FIELDS_5(fields) do { \
149 CHECK_PACKED_FIELDS_4(fields); \
150 CHECK_PACKED_FIELD(fields, 4); \
151} while (0)
152
153#define CHECK_PACKED_FIELDS_6(fields) do { \
154 CHECK_PACKED_FIELDS_5(fields); \
155 CHECK_PACKED_FIELD(fields, 5); \
156} while (0)
157
158#define CHECK_PACKED_FIELDS_7(fields) do { \
159 CHECK_PACKED_FIELDS_6(fields); \
160 CHECK_PACKED_FIELD(fields, 6); \
161} while (0)
162
163#define CHECK_PACKED_FIELDS_8(fields) do { \
164 CHECK_PACKED_FIELDS_7(fields); \
165 CHECK_PACKED_FIELD(fields, 7); \
166} while (0)
167
168#define CHECK_PACKED_FIELDS_9(fields) do { \
169 CHECK_PACKED_FIELDS_8(fields); \
170 CHECK_PACKED_FIELD(fields, 8); \
171} while (0)
172
173#define CHECK_PACKED_FIELDS_10(fields) do { \
174 CHECK_PACKED_FIELDS_9(fields); \
175 CHECK_PACKED_FIELD(fields, 9); \
176} while (0)
177
178#define CHECK_PACKED_FIELDS_11(fields) do { \
179 CHECK_PACKED_FIELDS_10(fields); \
180 CHECK_PACKED_FIELD(fields, 10); \
181} while (0)
182
183#define CHECK_PACKED_FIELDS_12(fields) do { \
184 CHECK_PACKED_FIELDS_11(fields); \
185 CHECK_PACKED_FIELD(fields, 11); \
186} while (0)
187
188#define CHECK_PACKED_FIELDS_13(fields) do { \
189 CHECK_PACKED_FIELDS_12(fields); \
190 CHECK_PACKED_FIELD(fields, 12); \
191} while (0)
192
193#define CHECK_PACKED_FIELDS_14(fields) do { \
194 CHECK_PACKED_FIELDS_13(fields); \
195 CHECK_PACKED_FIELD(fields, 13); \
196} while (0)
197
198#define CHECK_PACKED_FIELDS_15(fields) do { \
199 CHECK_PACKED_FIELDS_14(fields); \
200 CHECK_PACKED_FIELD(fields, 14); \
201} while (0)
202
203#define CHECK_PACKED_FIELDS_16(fields) do { \
204 CHECK_PACKED_FIELDS_15(fields); \
205 CHECK_PACKED_FIELD(fields, 15); \
206} while (0)
207
208#define CHECK_PACKED_FIELDS_17(fields) do { \
209 CHECK_PACKED_FIELDS_16(fields); \
210 CHECK_PACKED_FIELD(fields, 16); \
211} while (0)
212
213#define CHECK_PACKED_FIELDS_18(fields) do { \
214 CHECK_PACKED_FIELDS_17(fields); \
215 CHECK_PACKED_FIELD(fields, 17); \
216} while (0)
217
218#define CHECK_PACKED_FIELDS_19(fields) do { \
219 CHECK_PACKED_FIELDS_18(fields); \
220 CHECK_PACKED_FIELD(fields, 18); \
221} while (0)
222
223#define CHECK_PACKED_FIELDS_20(fields) do { \
224 CHECK_PACKED_FIELDS_19(fields); \
225 CHECK_PACKED_FIELD(fields, 19); \
226} while (0)
227
228#define CHECK_PACKED_FIELDS_21(fields) do { \
229 CHECK_PACKED_FIELDS_20(fields); \
230 CHECK_PACKED_FIELD(fields, 20); \
231} while (0)
232
233#define CHECK_PACKED_FIELDS_22(fields) do { \
234 CHECK_PACKED_FIELDS_21(fields); \
235 CHECK_PACKED_FIELD(fields, 21); \
236} while (0)
237
238#define CHECK_PACKED_FIELDS_23(fields) do { \
239 CHECK_PACKED_FIELDS_22(fields); \
240 CHECK_PACKED_FIELD(fields, 22); \
241} while (0)
242
243#define CHECK_PACKED_FIELDS_24(fields) do { \
244 CHECK_PACKED_FIELDS_23(fields); \
245 CHECK_PACKED_FIELD(fields, 23); \
246} while (0)
247
248#define CHECK_PACKED_FIELDS_25(fields) do { \
249 CHECK_PACKED_FIELDS_24(fields); \
250 CHECK_PACKED_FIELD(fields, 24); \
251} while (0)
252
253#define CHECK_PACKED_FIELDS_26(fields) do { \
254 CHECK_PACKED_FIELDS_25(fields); \
255 CHECK_PACKED_FIELD(fields, 25); \
256} while (0)
257
258#define CHECK_PACKED_FIELDS_27(fields) do { \
259 CHECK_PACKED_FIELDS_26(fields); \
260 CHECK_PACKED_FIELD(fields, 26); \
261} while (0)
262
263#define CHECK_PACKED_FIELDS_28(fields) do { \
264 CHECK_PACKED_FIELDS_27(fields); \
265 CHECK_PACKED_FIELD(fields, 27); \
266} while (0)
267
268#define CHECK_PACKED_FIELDS_29(fields) do { \
269 CHECK_PACKED_FIELDS_28(fields); \
270 CHECK_PACKED_FIELD(fields, 28); \
271} while (0)
272
273#define CHECK_PACKED_FIELDS_30(fields) do { \
274 CHECK_PACKED_FIELDS_29(fields); \
275 CHECK_PACKED_FIELD(fields, 29); \
276} while (0)
277
278#define CHECK_PACKED_FIELDS_31(fields) do { \
279 CHECK_PACKED_FIELDS_30(fields); \
280 CHECK_PACKED_FIELD(fields, 30); \
281} while (0)
282
283#define CHECK_PACKED_FIELDS_32(fields) do { \
284 CHECK_PACKED_FIELDS_31(fields); \
285 CHECK_PACKED_FIELD(fields, 31); \
286} while (0)
287
288#define CHECK_PACKED_FIELDS_33(fields) do { \
289 CHECK_PACKED_FIELDS_32(fields); \
290 CHECK_PACKED_FIELD(fields, 32); \
291} while (0)
292
293#define CHECK_PACKED_FIELDS_34(fields) do { \
294 CHECK_PACKED_FIELDS_33(fields); \
295 CHECK_PACKED_FIELD(fields, 33); \
296} while (0)
297
298#define CHECK_PACKED_FIELDS_35(fields) do { \
299 CHECK_PACKED_FIELDS_34(fields); \
300 CHECK_PACKED_FIELD(fields, 34); \
301} while (0)
302
303#define CHECK_PACKED_FIELDS_36(fields) do { \
304 CHECK_PACKED_FIELDS_35(fields); \
305 CHECK_PACKED_FIELD(fields, 35); \
306} while (0)
307
308#define CHECK_PACKED_FIELDS_37(fields) do { \
309 CHECK_PACKED_FIELDS_36(fields); \
310 CHECK_PACKED_FIELD(fields, 36); \
311} while (0)
312
313#define CHECK_PACKED_FIELDS_38(fields) do { \
314 CHECK_PACKED_FIELDS_37(fields); \
315 CHECK_PACKED_FIELD(fields, 37); \
316} while (0)
317
318#define CHECK_PACKED_FIELDS_39(fields) do { \
319 CHECK_PACKED_FIELDS_38(fields); \
320 CHECK_PACKED_FIELD(fields, 38); \
321} while (0)
322
323#define CHECK_PACKED_FIELDS_40(fields) do { \
324 CHECK_PACKED_FIELDS_39(fields); \
325 CHECK_PACKED_FIELD(fields, 39); \
326} while (0)
327
328#define CHECK_PACKED_FIELDS_41(fields) do { \
329 CHECK_PACKED_FIELDS_40(fields); \
330 CHECK_PACKED_FIELD(fields, 40); \
331} while (0)
332
333#define CHECK_PACKED_FIELDS_42(fields) do { \
334 CHECK_PACKED_FIELDS_41(fields); \
335 CHECK_PACKED_FIELD(fields, 41); \
336} while (0)
337
338#define CHECK_PACKED_FIELDS_43(fields) do { \
339 CHECK_PACKED_FIELDS_42(fields); \
340 CHECK_PACKED_FIELD(fields, 42); \
341} while (0)
342
343#define CHECK_PACKED_FIELDS_44(fields) do { \
344 CHECK_PACKED_FIELDS_43(fields); \
345 CHECK_PACKED_FIELD(fields, 43); \
346} while (0)
347
348#define CHECK_PACKED_FIELDS_45(fields) do { \
349 CHECK_PACKED_FIELDS_44(fields); \
350 CHECK_PACKED_FIELD(fields, 44); \
351} while (0)
352
353#define CHECK_PACKED_FIELDS_46(fields) do { \
354 CHECK_PACKED_FIELDS_45(fields); \
355 CHECK_PACKED_FIELD(fields, 45); \
356} while (0)
357
358#define CHECK_PACKED_FIELDS_47(fields) do { \
359 CHECK_PACKED_FIELDS_46(fields); \
360 CHECK_PACKED_FIELD(fields, 46); \
361} while (0)
362
363#define CHECK_PACKED_FIELDS_48(fields) do { \
364 CHECK_PACKED_FIELDS_47(fields); \
365 CHECK_PACKED_FIELD(fields, 47); \
366} while (0)
367
368#define CHECK_PACKED_FIELDS_49(fields) do { \
369 CHECK_PACKED_FIELDS_48(fields); \
370 CHECK_PACKED_FIELD(fields, 48); \
371} while (0)
372
373#define CHECK_PACKED_FIELDS_50(fields) do { \
374 CHECK_PACKED_FIELDS_49(fields); \
375 CHECK_PACKED_FIELD(fields, 49); \
376} while (0)
377
378#define CHECK_PACKED_FIELDS(fields) \
379 __builtin_choose_expr(ARRAY_SIZE(fields) == 1, ({ CHECK_PACKED_FIELDS_1(fields); }), \
380 __builtin_choose_expr(ARRAY_SIZE(fields) == 2, ({ CHECK_PACKED_FIELDS_2(fields); }), \
381 __builtin_choose_expr(ARRAY_SIZE(fields) == 3, ({ CHECK_PACKED_FIELDS_3(fields); }), \
382 __builtin_choose_expr(ARRAY_SIZE(fields) == 4, ({ CHECK_PACKED_FIELDS_4(fields); }), \
383 __builtin_choose_expr(ARRAY_SIZE(fields) == 5, ({ CHECK_PACKED_FIELDS_5(fields); }), \
384 __builtin_choose_expr(ARRAY_SIZE(fields) == 6, ({ CHECK_PACKED_FIELDS_6(fields); }), \
385 __builtin_choose_expr(ARRAY_SIZE(fields) == 7, ({ CHECK_PACKED_FIELDS_7(fields); }), \
386 __builtin_choose_expr(ARRAY_SIZE(fields) == 8, ({ CHECK_PACKED_FIELDS_8(fields); }), \
387 __builtin_choose_expr(ARRAY_SIZE(fields) == 9, ({ CHECK_PACKED_FIELDS_9(fields); }), \
388 __builtin_choose_expr(ARRAY_SIZE(fields) == 10, ({ CHECK_PACKED_FIELDS_10(fields); }), \
389 __builtin_choose_expr(ARRAY_SIZE(fields) == 11, ({ CHECK_PACKED_FIELDS_11(fields); }), \
390 __builtin_choose_expr(ARRAY_SIZE(fields) == 12, ({ CHECK_PACKED_FIELDS_12(fields); }), \
391 __builtin_choose_expr(ARRAY_SIZE(fields) == 13, ({ CHECK_PACKED_FIELDS_13(fields); }), \
392 __builtin_choose_expr(ARRAY_SIZE(fields) == 14, ({ CHECK_PACKED_FIELDS_14(fields); }), \
393 __builtin_choose_expr(ARRAY_SIZE(fields) == 15, ({ CHECK_PACKED_FIELDS_15(fields); }), \
394 __builtin_choose_expr(ARRAY_SIZE(fields) == 16, ({ CHECK_PACKED_FIELDS_16(fields); }), \
395 __builtin_choose_expr(ARRAY_SIZE(fields) == 17, ({ CHECK_PACKED_FIELDS_17(fields); }), \
396 __builtin_choose_expr(ARRAY_SIZE(fields) == 18, ({ CHECK_PACKED_FIELDS_18(fields); }), \
397 __builtin_choose_expr(ARRAY_SIZE(fields) == 19, ({ CHECK_PACKED_FIELDS_19(fields); }), \
398 __builtin_choose_expr(ARRAY_SIZE(fields) == 20, ({ CHECK_PACKED_FIELDS_20(fields); }), \
399 __builtin_choose_expr(ARRAY_SIZE(fields) == 21, ({ CHECK_PACKED_FIELDS_21(fields); }), \
400 __builtin_choose_expr(ARRAY_SIZE(fields) == 22, ({ CHECK_PACKED_FIELDS_22(fields); }), \
401 __builtin_choose_expr(ARRAY_SIZE(fields) == 23, ({ CHECK_PACKED_FIELDS_23(fields); }), \
402 __builtin_choose_expr(ARRAY_SIZE(fields) == 24, ({ CHECK_PACKED_FIELDS_24(fields); }), \
403 __builtin_choose_expr(ARRAY_SIZE(fields) == 25, ({ CHECK_PACKED_FIELDS_25(fields); }), \
404 __builtin_choose_expr(ARRAY_SIZE(fields) == 26, ({ CHECK_PACKED_FIELDS_26(fields); }), \
405 __builtin_choose_expr(ARRAY_SIZE(fields) == 27, ({ CHECK_PACKED_FIELDS_27(fields); }), \
406 __builtin_choose_expr(ARRAY_SIZE(fields) == 28, ({ CHECK_PACKED_FIELDS_28(fields); }), \
407 __builtin_choose_expr(ARRAY_SIZE(fields) == 29, ({ CHECK_PACKED_FIELDS_29(fields); }), \
408 __builtin_choose_expr(ARRAY_SIZE(fields) == 30, ({ CHECK_PACKED_FIELDS_30(fields); }), \
409 __builtin_choose_expr(ARRAY_SIZE(fields) == 31, ({ CHECK_PACKED_FIELDS_31(fields); }), \
410 __builtin_choose_expr(ARRAY_SIZE(fields) == 32, ({ CHECK_PACKED_FIELDS_32(fields); }), \
411 __builtin_choose_expr(ARRAY_SIZE(fields) == 33, ({ CHECK_PACKED_FIELDS_33(fields); }), \
412 __builtin_choose_expr(ARRAY_SIZE(fields) == 34, ({ CHECK_PACKED_FIELDS_34(fields); }), \
413 __builtin_choose_expr(ARRAY_SIZE(fields) == 35, ({ CHECK_PACKED_FIELDS_35(fields); }), \
414 __builtin_choose_expr(ARRAY_SIZE(fields) == 36, ({ CHECK_PACKED_FIELDS_36(fields); }), \
415 __builtin_choose_expr(ARRAY_SIZE(fields) == 37, ({ CHECK_PACKED_FIELDS_37(fields); }), \
416 __builtin_choose_expr(ARRAY_SIZE(fields) == 38, ({ CHECK_PACKED_FIELDS_38(fields); }), \
417 __builtin_choose_expr(ARRAY_SIZE(fields) == 39, ({ CHECK_PACKED_FIELDS_39(fields); }), \
418 __builtin_choose_expr(ARRAY_SIZE(fields) == 40, ({ CHECK_PACKED_FIELDS_40(fields); }), \
419 __builtin_choose_expr(ARRAY_SIZE(fields) == 41, ({ CHECK_PACKED_FIELDS_41(fields); }), \
420 __builtin_choose_expr(ARRAY_SIZE(fields) == 42, ({ CHECK_PACKED_FIELDS_42(fields); }), \
421 __builtin_choose_expr(ARRAY_SIZE(fields) == 43, ({ CHECK_PACKED_FIELDS_43(fields); }), \
422 __builtin_choose_expr(ARRAY_SIZE(fields) == 44, ({ CHECK_PACKED_FIELDS_44(fields); }), \
423 __builtin_choose_expr(ARRAY_SIZE(fields) == 45, ({ CHECK_PACKED_FIELDS_45(fields); }), \
424 __builtin_choose_expr(ARRAY_SIZE(fields) == 46, ({ CHECK_PACKED_FIELDS_46(fields); }), \
425 __builtin_choose_expr(ARRAY_SIZE(fields) == 47, ({ CHECK_PACKED_FIELDS_47(fields); }), \
426 __builtin_choose_expr(ARRAY_SIZE(fields) == 48, ({ CHECK_PACKED_FIELDS_48(fields); }), \
427 __builtin_choose_expr(ARRAY_SIZE(fields) == 49, ({ CHECK_PACKED_FIELDS_49(fields); }), \
428 __builtin_choose_expr(ARRAY_SIZE(fields) == 50, ({ CHECK_PACKED_FIELDS_50(fields); }), \
429 ({ BUILD_BUG_ON_MSG(1, "CHECK_PACKED_FIELDS() must be regenerated to support array sizes larger than 50."); }) \
430))))))))))))))))))))))))))))))))))))))))))))))))))
431
432/* End of generated content */
433
434#define pack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
435 ({ \
436 CHECK_PACKED_FIELDS(fields); \
437 CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
438 _Generic((fields), \
439 const struct packed_field_u8 * : pack_fields_u8, \
440 const struct packed_field_u16 * : pack_fields_u16 \
441 )((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
442 })
443
444#define unpack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
445 ({ \
446 CHECK_PACKED_FIELDS(fields); \
447 CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
448 _Generic((fields), \
449 const struct packed_field_u8 * : unpack_fields_u8, \
450 const struct packed_field_u16 * : unpack_fields_u16 \
451 )((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
452 })
453
454#endif