Day111 Lab — IIO Buffered Acquisition and Scan Packing¶
Goal¶
Build a simplified IIO buffered-acquisition simulator that models the relationship between:
- Fixed ADC hardware scan layout
- IIO channel metadata
- Active scan masks
- Logical scan size
- Single-scan packing
- Multi-scan block packing
- Direct DMA-compatible layouts
- Sparse layouts that require repacking
The lab focuses on the data-layout boundary between DMA and IIO.
The simulator does not reproduce the internal implementation of the Linux IIO subsystem.
1. Hardware Model¶
The simulated ADC provides four channels:
Each hardware sample uses 16-bit storage:
Therefore one complete hardware scan occupies:
The hardware scan layout is fixed even when the logical IIO configuration disables a channel.
For example, disabling CH1 does not change the DMA-visible hardware frame:
The logical IIO scan may instead request:
This difference is the main problem modeled by the lab.
2. Simulated IIO Channel Model¶
Each simulated channel describes:
The lab uses:
static const struct sim_iio_channel adc_channels[] = {
{
.channel = 0,
.scan_index = 0,
.storage_bytes = sizeof(uint16_t),
},
{
.channel = 1,
.scan_index = 1,
.storage_bytes = sizeof(uint16_t),
},
{
.channel = 2,
.scan_index = 2,
.storage_bytes = sizeof(uint16_t),
},
{
.channel = 3,
.scan_index = 3,
.storage_bytes = sizeof(uint16_t),
},
};
For this simulator:
The scan index determines the corresponding bit position in the active scan mask.
3. Active Scan Configuration¶
The simulated scan configuration contains:
The full scan mask is:
With 2 bytes per channel:
A sparse scan mask used by the lab is:
The resulting logical scan size is:
scan_bytes represents the logical size of one enabled IIO scan.
It is not the size of the fixed hardware scan.
4. Scan Configuration API¶
The simulator initializes the IIO device using:
bool sim_iio_device_init(struct sim_iio_device *indio_dev,
const struct sim_iio_channel *channels,
size_t num_channels);
The active scan configuration is applied using:
The configuration logic:
- Validates the device and channel table.
- Rejects an empty scan mask.
- Builds the valid mask from channel
scan_indexvalues. - Rejects unsupported scan bits.
- Adds the
storage_bytesof enabled channels. - Commits the resulting
active_scan_maskandscan_bytes.
Channel state can be queried using:
5. Hardware Scan vs Logical Scan¶
The relationship between the fixed DMA layout and logical IIO layout is shown below.
For a full scan:
The layouts match.
For a sparse scan:
The logical layout is smaller and requires repacking.
6. Single-Scan Packing¶
One hardware scan is converted using:
bool sim_iio_pack_scan(const struct sim_iio_device *indio_dev,
const void *hw_scan,
size_t hw_scan_bytes,
void *iio_scan,
size_t iio_scan_capacity);
The API operates on exactly one complete hardware scan.
Therefore:
is required.
A larger input is not silently accepted as multiple scans.
Sparse Example¶
Input:
Configuration:
Output:
The packing algorithm maintains two offsets:
hw_offset
→ advances for every hardware channel
iio_offset
→ advances only when the channel is enabled
Conceptually:
CH0 enabled
copy
hw_offset += 2
iio_offset += 2
CH1 disabled
skip
hw_offset += 2
iio_offset unchanged
CH2 enabled
copy
hw_offset += 2
iio_offset += 2
CH3 enabled
copy
hw_offset += 2
iio_offset += 2
The final sizes are:
7. Hardware Scan Size Helper¶
The hardware scan size is independent of the active logical scan mask.
The simulator therefore calculates it from all hardware channels:
Conceptually:
For this lab:
This must not be confused with:
which represents the currently configured logical scan.
8. Block-Level Packing¶
A DMA transfer commonly contains multiple complete hardware scans.
The simulator therefore provides:
bool sim_iio_pack_block(const struct sim_iio_device *indio_dev,
const void *hw_block,
size_t hw_block_bytes,
size_t hw_scan_bytes,
void *iio_block,
size_t iio_block_capacity,
size_t *iio_block_bytes);
The input block must contain only complete scans:
The number of scans is:
The required output size is:
The block-level API does not duplicate channel-selection logic.
Instead, it repeatedly calls:
for each complete hardware scan.
9. Block Conversion Example¶
The lab uses four hardware scans:
Scan 0:
0x1000 0x1100 0x1200 0x1300
Scan 1:
0x2000 0x2100 0x2200 0x2300
Scan 2:
0x3000 0x3100 0x3200 0x3300
Scan 3:
0x4000 0x4100 0x4200 0x4300
Each hardware scan occupies:
Therefore:
With:
each logical scan occupies:
and the resulting logical block occupies:
The expected logical values are:
Scan 0:
0x1000 0x1200 0x1300
Scan 1:
0x2000 0x2200 0x2300
Scan 2:
0x3000 0x3200 0x3300
Scan 3:
0x4000 0x4200 0x4300
10. DMA Compatibility¶
The simulator also distinguishes between logical layouts that match the fixed DMA hardware layout and layouts that require transformation.
The API is:
For the fixed four-channel hardware model:
active_scan_mask = 0xF
→ CH0 CH1 CH2 CH3
→ DMA compatible
active_scan_mask = 0xD
→ CH0 CH2 CH3
→ repacking required
This models a possible real driver policy.
A driver may choose between:
The lab implements repacking so that both layouts can be examined.
11. Buffered Acquisition Context¶
The simulator focuses on scan layout rather than reproducing the complete IIO buffer implementation.
The architectural context is:
The important separation is:
DMA
→ transfers the hardware representation
IIO scan configuration
→ defines the logical representation
When these representations match, a direct DMA-backed layout is possible.
When they differ, software transformation may be required.
12. Test Cases¶
Case 1 — Full Scan Mask¶
Configure:
Expected:
Observed:
Case 2 — Sparse Scan Mask¶
Configure:
Expected:
Observed:
Case 3 — Empty Scan Mask¶
Configure:
Expected:
Observed:
Case 4 — Sparse Scan Repacking¶
Input:
Expected:
Observed:
[CASE 4] Sparse scan repacking
[PASS] input : 0x1000 0x2000 0x3000 0x4000
[PASS] output: 0x1000 0x3000 0x4000
Case 5 — Full Scan Packing¶
Input:
Expected:
Observed:
[CASE 5] Full scan packing
[PASS] input : 0x1000 0x2000 0x3000 0x4000
[PASS] output: 0x1000 0x2000 0x3000 0x4000
Case 6 — Sparse Block Packing¶
Input:
Expected:
Observed:
Case 7 — DMA Scan Compatibility¶
Expected:
Observed:
[CASE 7] DMA scan compatibility
[PASS] full scan is DMA compatible
[PASS] sparse scan requires repacking
13. Final Test Result¶
The complete test run finishes with:
The simulator therefore verifies:
- Active scan-mask handling
- Logical scan-size calculation
- Empty-mask rejection
- Fixed hardware scan validation
- Sparse single-scan repacking
- Full-layout packing
- Multi-scan block conversion
- Produced-byte accounting
- DMA layout compatibility
Key Takeaways¶
-
DMA transfers the hardware-defined data representation.
-
An IIO active scan mask describes the logical buffered representation.
-
scan_indexdetermines the channel's scan-mask bit position. -
scan_bytesfollows enabled element storage size rather than only ADC resolution. -
A fixed hardware frame may remain unchanged when a logical channel is disabled.
-
If the hardware and logical layouts differ, compact logical scans require repacking or the configuration must be rejected.
-
One hardware scan and one logical IIO scan can have different sizes.
-
A multi-scan DMA block can therefore produce a smaller logical IIO block after repacking.
-
Direct DMA-backed buffering is simplest when the hardware scan layout already matches the consumer-visible IIO scan layout.
-
Scan-layout transformation belongs above the raw DMA transport model and should not be confused with DMA ownership or mapping lifetime.