Skip to content

Repository files navigation

Linux Device Driver Development — Virtual Industrial Sensor Controller

[Linux Kernel] [Driver] [Language] [Build] [Userspace] [Virtualization] [Repository]

A portfolio-grade Linux kernel driver project for a virtual industrial sensor controller, demonstrating character-device I/O, ioctl ABI design, sysfs/procfs/debugfs interfaces, concurrent buffering, periodic telemetry, Device Tree integration, userspace tooling, automated testing, and QEMU-based validation.


Project at a Glance

This project implements a virtual industrial sensor controller as a Linux kernel driver.

The driver models a telemetry-producing device that generates sensor samples, maintains device state and statistics, stores samples in a bounded kernel buffer, and exposes controlled interfaces to userspace.

The repository is organized as a complete engineering project rather than a single source file:

  • Linux kernel module
  • platform-driver architecture
  • character-device interface
  • ioctl userspace ABI
  • sysfs configuration/status
  • procfs runtime reporting
  • debugfs diagnostics
  • bounded concurrent sample buffering
  • delayed-work telemetry generation
  • Device Tree description and binding
  • userspace control utility
  • userspace test programs
  • QEMU build/run/test tooling
  • architecture and concurrency documentation
  • GitHub repository templates and CI structure
  • Doxygen configuration
  • validation/evidence structure

Why This Project Matters

The project is designed to demonstrate the engineering boundary between:

device behavior → Linux kernel subsystems → synchronization → kernel/userspace ABI → userspace control → virtualized validation

It focuses on practical systems-level concepts relevant to Embedded Linux, Linux kernel development, device drivers, firmware and embedded software.

Engineering Area Demonstrated Implementation
Kernel modules vsensor.ko
Platform driver platform_driver + probe/remove
Character devices cdev and device registration
Userspace ABI ioctl structures and commands
Synchronization mutexes, spinlocks and wait queues
Deferred execution Linux delayed work
Data buffering bounded circular sample buffer
Device configuration sysfs + ioctl
Diagnostics procfs + debugfs
Device Tree DTS + YAML binding
Virtual validation QEMU
Userspace tooling driverctl
Testing five userspace test programs
Repository engineering CI, issue templates, PR template
Documentation Markdown + Doxygen configuration

Architecture

flowchart TB
    U["Userspace Applications"]
    CLI["driverctl<br/>Control Utility"]
    TEST["Userspace Tests"]

    ABI["Character Device<br/>read/write/poll/ioctl"]
    SYS["sysfs"]
    PROC["procfs"]
    DBG["debugfs"]

    CORE["Virtual Sensor Core Driver"]
    BUF["Concurrent Sample Buffer"]
    TEL["Telemetry Engine<br/>delayed_work"]
    PLAT["Platform Driver"]

    DT["Device Tree / Platform Device"]
    QEMU["QEMU Environment"]
    K["Linux Kernel 6.12"]

    U --> CLI
    TEST --> ABI
    CLI --> ABI
    CLI --> SYS

    ABI --> CORE
    SYS --> CORE
    PROC --> CORE
    DBG --> CORE

    CORE --> BUF
    CORE --> TEL
    PLAT --> CORE
    DT --> PLAT

    CORE --> K
    QEMU --> K
Loading

Telemetry Data Flow

sequenceDiagram
    participant W as Delayed Work
    participant D as Sensor Driver
    participant B as Sample Buffer
    participant U as Userspace

    W->>D: Generate sensor sample
    D->>D: Update state, sequence and statistics
    D->>B: Push sample
    B-->>D: Queue result
    D->>U: Wake waiting readers
    U->>D: read()/poll()/ioctl()
    D->>B: Pop sample
    B-->>D: Sample
    D-->>U: Copy sample to userspace
Loading

Core Features

1. Character Device

The driver provides standard Linux character-device operations:

open
release
read
write
poll
unlocked_ioctl

This gives userspace a conventional kernel-device interface.


2. ioctl ABI

The userspace ABI is defined in:

driver/include/virtual_sensor_uapi.h

The project defines structured control/status operations such as:

GET_SAMPLE
GET_STATS
GET_CONFIG
SET_CONFIG
START
STOP
RESET

This separates structured device control from simple textual interfaces.


3. Periodic Telemetry

The telemetry subsystem uses Linux delayed work to periodically generate virtual sensor samples.

The driver maintains state including:

  • sequence number
  • timestamp
  • temperature
  • vibration
  • status flags
  • generated sample count
  • read count
  • dropped sample count
  • fault event count
  • open count

4. Concurrent Sample Buffer

Sensor samples are stored in a bounded circular buffer.

The implementation uses:

spin_lock_irqsave()
spin_unlock_irqrestore()
mutex
wait queue

The buffer protects producer/consumer state while the device-state lock protects broader configuration and runtime state.

This separation is important for demonstrating kernel concurrency design rather than relying on one global lock.


5. sysfs

The driver exposes runtime configuration/status through sysfs attributes including:

enabled
period_ms
sequence

These interfaces provide a Linux-native way to inspect and control device state.


6. procfs

A procfs status interface provides human-readable runtime information and telemetry statistics.


7. debugfs

The project provides a debugfs interface for development-time diagnostics and driver observability.


8. Device Tree

The repository contains:

dts/virtual-sensor.dts
dts/bindings/prasanth,virtual-sensor.yaml

The binding describes the virtual industrial sensor device and its configurable properties.


9. Virtual/QEMU Device Path

The project includes a QEMU environment for reproducible virtual validation.

Where a normal x86 QEMU configuration does not expose the intended Device Tree path, the driver architecture includes a controlled virtual platform-device path so that driver lifecycle and userspace interaction can still be exercised.


Repository Structure

.
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── workflows/
│   │   └── ci.yml
│   └── pull_request_template.md
│
├── docs/
│   ├── ARCHITECTURE.md
│   ├── BUILD.md
│   ├── CONCURRENCY.md
│   ├── DEBUGGING.md
│   ├── DEVICE_TREE.md
│   ├── DRIVER_MODEL.md
│   ├── PHASE_1.md
│   ├── TESTING.md
│   ├── USERSPACE_ABI.md
│   └── RELEASE_CHECKLIST.md
│
├── driver/
│   ├── core/
│   │   ├── vsensor_buffer.c
│   │   ├── vsensor_buffer.h
│   │   ├── vsensor_core.c
│   │   ├── vsensor_debugfs.c
│   │   ├── vsensor_ioctl.c
│   │   ├── vsensor_sysfs.c
│   │   └── vsensor_telemetry.c
│   ├── include/
│   │   ├── virtual_sensor.h
│   │   └── virtual_sensor_uapi.h
│   ├── irq/
│   ├── platform/
│   ├── kconfig
│   └── Makefile
│
├── dts/
├── qemu/
├── scripts/
├── tests/
├── tools/
├── userspace/
├── screenshots/
├── Doxyfile
├── Makefile
└── README.md

Build Environment

The current validation environment reports:

Linux kernel: 6.12.0
Driver build: Kbuild
Userspace:    C
Virtual test: QEMU

The driver artifact has been produced as:

vsensor.ko

with verified metadata:

version:  1.0.0
name:     vsensor
vermagic: 6.12.0 SMP preempt mod_unload

Build the Kernel Module

The project builds the external kernel module against a prepared Linux kernel source tree.

Example:

KDIR="$HOME/embedded-kernel-project/linux"
BUILD="$HOME/driver-build"

make -C "$KDIR" M="$BUILD" clean
make -C "$KDIR" M="$BUILD" modules

Inspect the resulting module:

modinfo "$BUILD/vsensor.ko"

Build the Userspace Utility

make -C userspace/driverctl clean
make -C userspace/driverctl

Output:

userspace/driverctl/driverctl

The current project validation produced the userspace executable successfully.


Userspace Tests

The repository contains five test programs:

userspace/tests/test_basic.c
userspace/tests/test_concurrency.c
userspace/tests/test_errors.c
userspace/tests/test_ioctl.c
userspace/tests/test_poll.c

They are built into:

build/tests/

The validated build produced:

test_basic
test_concurrency
test_errors
test_ioctl
test_poll

Build example:

mkdir -p build/tests

cc -std=c11 -Wall -Wextra -Wpedantic -O2 \
    -I./driver/include \
    userspace/tests/test_basic.c \
    -o build/tests/test_basic

cc -std=c11 -Wall -Wextra -Wpedantic -O2 -pthread \
    -I./driver/include \
    userspace/tests/test_concurrency.c \
    -o build/tests/test_concurrency

cc -std=c11 -Wall -Wextra -Wpedantic -O2 \
    -I./driver/include \
    userspace/tests/test_errors.c \
    -o build/tests/test_errors

cc -std=c11 -Wall -Wextra -Wpedantic -O2 \
    -I./driver/include \
    userspace/tests/test_ioctl.c \
    -o build/tests/test_ioctl

cc -std=c11 -Wall -Wextra -Wpedantic -O2 \
    -I./driver/include \
    userspace/tests/test_poll.c \
    -o build/tests/test_poll

QEMU Validation

The repository provides:

qemu/build-kernel.sh
qemu/build-rootfs.sh
qemu/run-qemu.sh
qemu/run-tests.sh

The intended validation sequence is:

bash qemu/build-kernel.sh
bash qemu/build-rootfs.sh
bash qemu/run-qemu.sh
bash qemu/run-tests.sh

The project has already produced the required QEMU artifacts during development, including:

build/kernel/bzImage
build/rootfs.cpio.gz
build/dtb/virtual-sensor.dtb

The final release should retain the strongest terminal/QEMU evidence in:

screenshots/

Testing Strategy

Userspace Test Layer

test_basic
test_concurrency
test_errors
test_ioctl
test_poll

Integration Layer

tests/integration/
tests/scripts/run_userspace_tests.sh

Driver Validation

The project validation process covers:

  • kernel-module compilation
  • module metadata inspection
  • userspace utility compilation
  • userspace test compilation
  • QEMU image preparation
  • QEMU execution
  • driver/userspace integration
  • source-tree audit
  • repository hygiene

Concurrency Design

Different categories of shared state use different synchronization mechanisms.

Device State

The driver uses a mutex for broader device-state/configuration protection:

struct mutex state_lock;

Sample Buffer

The bounded buffer uses spinlock-based protection:

spin_lock_irqsave()
spin_unlock_irqrestore()

Blocking Reads

A wait queue allows readers to sleep until data becomes available instead of busy-waiting.

Periodic Work

Telemetry generation uses:

struct delayed_work

rather than creating an unnecessary dedicated kernel thread.


Userspace / Kernel Observability

Interface Primary Purpose
Character device Primary device interaction
read() Retrieve queued samples
write() Textual control path
poll() Event-driven waiting
ioctl() Structured configuration/control
sysfs Device configuration/status
procfs Human-readable runtime status
debugfs Development diagnostics

The project therefore demonstrates multiple Linux interfaces instead of forcing every operation through a single ABI.


Error Handling

The implementation includes explicit handling for conditions such as:

  • invalid userspace arguments
  • invalid configuration values
  • failed userspace copies
  • empty buffers
  • full buffers
  • registration failures
  • device/class creation failures
  • sysfs initialization failures
  • debugfs initialization failures
  • platform-device registration failures

Representative kernel error codes include:

-EINVAL
-EFAULT
-ENODEV
-EAGAIN
-ENOSPC
-ENOMEM
-ENOTTY

Static / Repository Quality

The repository contains:

scripts/build_driver.sh
scripts/build_userspace.sh
scripts/static_analysis.sh
tools/check_kernel_style.sh
tools/collect_evidence.sh

The repository audit performed during development covered:

Source-tree inventory
Empty-file detection
Placeholder/TODO scan
Suspicious stub detection
Debug-print scan
Secret/credential scan
Git whitespace validation
Generated-artifact filtering

Development backup material was removed before release preparation.

Generated build outputs are excluded through .gitignore.


Documentation

The documentation is organized by engineering topic:

docs/ARCHITECTURE.md
docs/BUILD.md
docs/CONCURRENCY.md
docs/DEBUGGING.md
docs/DEVICE_TREE.md
docs/DRIVER_MODEL.md
docs/PHASE_1.md
docs/TESTING.md
docs/USERSPACE_ABI.md

Doxygen is configured through:

Doxyfile

Generate API documentation with:

doxygen Doxyfile

Generated documentation should remain a build artifact unless the repository explicitly chooses to publish it.


Evidence & Screenshots

Validation evidence belongs in:

screenshots/

Recommended final evidence set:

Evidence Suggested File
Driver build 01-driver-build.png
Module metadata 02-modinfo.png
Userspace build 03-userspace-build.png
Test build/results 04-tests.png
QEMU boot 05-qemu-boot.png
Driver probe 06-driver-probe.png
Device node 07-device-node.png
ioctl 08-ioctl.png
sysfs 09-sysfs.png
procfs/debugfs 10-observability.png
Final validation 11-final-validation.png

A short terminal transcript can accompany screenshots where it gives stronger reproducibility than an image alone.

When the final screenshots are captured, they can be referenced here with normal GitHub-relative image links.


CI / GitHub Engineering

The repository is prepared for a professional GitHub workflow:

.github/
├── ISSUE_TEMPLATE/
│   ├── bug_report.md
│   └── feature_request.md
├── workflows/
│   └── ci.yml
└── pull_request_template.md

Repository governance files include:

CONTRIBUTING.md
CODE_OF_CONDUCT.md
SECURITY.md
CHANGELOG.md
LICENSE

The CI workflow is intended to verify userspace builds and repository validation automatically.


Engineering Highlights

This project demonstrates hands-on work with:

  • Linux kernel modules
  • platform drivers
  • character devices
  • Kbuild
  • Device Tree
  • ioctl ABI design
  • sysfs
  • procfs
  • debugfs
  • wait queues
  • mutexes
  • spinlocks
  • delayed work
  • bounded circular buffers
  • kernel/userspace data exchange
  • QEMU
  • embedded Linux validation
  • defensive error handling
  • userspace testing
  • repository CI
  • engineering documentation

Limitations

This is a virtual sensor controller, not a physical industrial sensor driver.

Therefore:

  • sensor values are simulated
  • no physical SPI/I2C sensor is required
  • QEMU provides the virtual validation environment
  • hardware-specific acquisition would require a real sensor backend
  • physical interrupt/DMA behavior would be added when integrating actual hardware

These limitations are deliberate. The project concentrates on Linux driver architecture, synchronization, ABI design, observability and reproducible validation.


Future Extensions

Potential next-stage engineering extensions include:

  • real I2C/SPI sensor backend
  • hardware IRQ-driven acquisition
  • DMA-based data path
  • kernel tracepoints
  • ftrace/perf instrumentation
  • fault-injection testing
  • KUnit tests
  • broader kernel-version CI
  • automated QEMU boot tests
  • performance and latency benchmarks
  • industrial protocol integration

Project Status

Current Milestone: Release Preparation

Completed

  • Linux kernel driver implementation
  • Driver module build
  • vsensor.ko metadata verification
  • Userspace utility build
  • Five userspace test builds
  • QEMU kernel/rootfs/DTB artifacts generated
  • Source-tree audit
  • Development backup removed
  • Generated build artifacts excluded from Git
  • Placeholder scan
  • Secret/credential scan
  • Repository whitespace validation
  • Professional GitHub structure
  • Doxygen configuration
  • Professional README

Final Release Tasks

  • Final QEMU execution capture
  • Capture final terminal evidence
  • Populate screenshots/
  • Review README rendering after assets are added
  • Final Git staging audit
  • Create first release commit
  • Push repository to GitHub
  • Verify GitHub-rendered README
  • Verify CI result

This distinction is intentional: development validation is complete enough to package the project, while the final public-release evidence still needs to be captured.


Author

Venkata Prasanth

Embedded Systems • Linux Device Drivers • Embedded Software • Systems Programming

B.Tech — Electronics and Communication Engineering (ECE) Lendi Institute of Engineering and Technology Vizianagaram, Andhra Pradesh, India Expected graduation: 2027

Portfolio Focus

Embedded Linux
Linux Kernel
Device Drivers
Firmware Development
RTOS
Systems Programming
Embedded C

Contact

  • GitHub: github.com/prasanth-vedula
  • Email: prasanthvedula2006@gmail.com

License

See the repository's:

LICENSE

The repository should use the license declared by the actual LICENSE file; this README intentionally does not invent a license designation if the file has not yet been populated.


Final Engineering Perspective

This project is intended to demonstrate the complete engineering lifecycle:

Design
   ↓
Implement
   ↓
Build
   ↓
Test
   ↓
Validate
   ↓
Document
   ↓
Collect Evidence
   ↓
Package
   ↓
Review
   ↓
Release

The objective is not simply to demonstrate that a kernel module can compile.

The objective is to demonstrate that an embedded-systems engineer can take a systems problem, design a kernel/userspace boundary, implement synchronization and device behavior, build and validate it in a virtual environment, document the architecture, and package the result as a professional engineering repository.

Validation Evidence

This repository includes reproducible engineering evidence from the build, driver, userspace, QEMU, ABI, and final release-validation stages.

Build Environment

Build Environment

Driver Source Inventory

Source Inventory

Driver ABI Implementation

Driver ABI Implementation

Userspace Test Build

Userspace Test Build

QEMU Validation

QEMU Validation

Final Release Validation

Final Release Validation

PNG files are presentation snapshots generated directly from the projects actual validation records. The corresponding TXT/MD files remain the raw evidence records.

About

Production-style Linux kernel virtual industrial sensor controller with character-device I/O, ioctl, poll, sysfs, debugfs, telemetry buffering, Device Tree, QEMU validation, userspace tooling, tests, CI, and Doxygen documentation.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages