Skip to content

Day39 - IIO Capability Exposure

🎯 Goal

Enhance IIO driver usability by exposing supported configuration values to user-space.

Focus on:

  • sampling_frequency_available
  • Table-based validation
  • Clean separation of:
  • user-visible values (Hz)
  • hardware encoding (register values)

🧠 Design Overview

Control Plane Evolution

Stage Description
Day38 User can configure parameters
Day39 Driver exposes supported capabilities

📊 Sampling Frequency Design

Key Decision

sampling_frequency:
  > 0 → periodic sampling (Hz)
  = 0 → disable periodic sampling

Note:

  • 0 does NOT imply one-shot conversion
  • one-shot will be handled separately in future design

🧩 Mapping Table (Core Concept)

Problem

Hardware uses register encoding:

reg_val: 0,1,2,3,...

User-space expects:

Hz: 0,1,2,4,8,...

Solution

Use a mapping table:

struct myadc_sampling_freq {
    u8 reg_val;
    unsigned int hz;
};

static const struct myadc_sampling_freq myadc_sampling_freqs[] = {
    { MYADC_SR_DISABLE, 0   },
    { MYADC_SR_1_HZ,     1   },
    { MYADC_SR_2_HZ,     2   },
    { MYADC_SR_4_HZ,     4   },
    { MYADC_SR_8_HZ,     8   },
    { MYADC_SR_16_HZ,   16  },
    { MYADC_SR_32_HZ,   32  },
    { MYADC_SR_64_HZ,   64  },
    { MYADC_SR_128_HZ, 128  },
};

🔍 Lookup Helpers

static const struct myadc_sampling_freq *
myadc_find_sample_freq_by_hz(unsigned int hz);

static const struct myadc_sampling_freq *
myadc_find_sample_freq_by_reg(u8 reg_val);

Design Rules

  • Table is the single source of truth
  • No MAX-based validation
  • No duplicated logic

⚙️ Write Path (Validation)

Before (Day38)

if (val > MAX)
    return -EINVAL;

After (Day39)

if (!myadc_find_sample_freq_by_hz(val))
    return -EINVAL;

📤 Capability Exposure

sampling_frequency_available

Exposed as:

/sys/bus/iio/devices/iio:deviceX/sampling_frequency_available

Output Format

0 1 2 4 8 16 32 64 128

Implementation

static ssize_t myadc_sampling_frequency_available_show(
        struct device *dev,
        struct device_attribute *attr,
        char *buf)
{
    int i, len = 0;

    for (i = 0; i < ARRAY_SIZE(myadc_sampling_freqs); i++) {
        len += sysfs_emit_at(buf, len, "%u%s",
                             myadc_sampling_freqs[i].hz,
                             (i == ARRAY_SIZE(myadc_sampling_freqs) - 1)
                             ? "\n" : " ");
    }

    return len;
}

🔒 Concurrency Considerations

  • No lock required for _available
  • Uses static const table
  • No runtime state accessed

🧱 Design Principles

1. Separation of concerns

Layer Representation
user-space Hz
driver mapping table
hardware register encoding

2. Table as source of truth

  • Validation
  • Capability exposure
  • Register mapping

All derived from the same table.


3. Sysfs convention

  • _available attributes are read-only
  • values are space-separated
  • newline terminated

✅ Summary

  • Introduced capability exposure
  • Replaced MAX-based validation with table-based validation
  • Improved user-space usability
  • Established clean abstraction between hardware and API