Skip to content

Day 14 - Event-driven GPIO Driver

🎯 Goal

Transform a simple GPIO driver into an event-driven character device with:

  • Interrupt-based input handling
  • Software debounce (deferred work)
  • Event queue (ring buffer)
  • Blocking / non-blocking read
  • poll/select support

🧠 Key Concepts

1. Event-driven vs State-driven

Type Behavior
State device Read returns current status
Event device Read returns one event

👉 This driver is now an event stream device


2. IRQ Top Half + Bottom Half

Top Half (ISR)

static irqreturn_t mygpio_btn_isr(...)
{
    mod_delayed_work(...);
}
  • Must be fast
  • No sleeping
  • Only schedule work

Bottom Half (Delayed Work)

static void mygpio_btn_dwork_handler(...)
{
    gpiod_get_value_cansleep(...);
}
  • Runs in process context
  • Can sleep
  • Handles debounce + event generation

3. Software Debounce

  • Delay processing using delayed_work
  • Only report stable state change
if (value != last_reported_state)

4. Ring Buffer (Event Queue)

event_buff[EVENT_BUFFER_SIZE]
event_head
event_tail
  • FIFO queue
  • Single producer (worker)
  • Single consumer (read)

Full condition

next != event_tail

👉 Drop event if full


5. Blocking Read (wait queue)

wait_event_interruptible(...)

Behavior:

  • No event → sleep
  • Event arrives → wake up

6. Non-blocking Read

if (O_NONBLOCK && !has_event)
    return -EAGAIN;

7. poll / select support

poll_wait(...)

Return:

POLLIN | POLLRDNORM

8. Removal Safety

shutting_down = true;
wake_up_all(...)

Reader behavior:

  • Wake up
  • Return -ENODEV

9. Event Semantics

  • Each read = one event
  • Not snapshot
  • Continuous stream

🔄 Data Flow

IRQ
ISR (top half)
delayed_work
debounce + event push
ring buffer
wake_up_interruptible()
read() / poll()

⚠️ Design Decisions

Why not lock-free?

  • Only 1 producer + 1 consumer
  • mutex is simple and safe
  • lock-free not necessary here

Why READ_ONCE?

  • Avoid compiler reordering
  • Safe lockless check

Why not kfifo?

  • Custom ring buffer is sufficient
  • Learning purpose

📌 Summary

Day14 upgrades the driver to:

  • Interrupt-driven
  • Event-based
  • User-space friendly (poll/select)
  • Production-like design