Day12 - Event-Driven GPIO Driver with poll()¶
Goal¶
Upgrade the Day11 GPIO IRQ driver so that it supports:
- blocking read
- non-blocking read
- poll/select/epoll compatible event notification
Step 1 - Add Event Fields¶
Add the following fields into the device private structure:
Purpose¶
read_queue: used for sleep/wakeupevent_pending: indicates whether a new event is waitingevent_btn_state: stores the button state for the pending event
Step 2 - Initialize in probe()¶
Initialize the new fields in the probe function:
Step 3 - Update IRQ Handler¶
When an IRQ occurs:
- read the button state
- store it as pending event data
- wake up sleeping readers
Example logic:
mydev->btn_state = value;
mydev->event_btn_state = value;
mydev->event_pending = 1;
wake_up_interruptible(&mydev->read_queue);
Step 4 - Implement Blocking Read¶
In blocking mode, read() should sleep until an event becomes available.
Core logic:
After wakeup:
- copy event data
- clear
event_pending
Example:
Step 5 - Add Non-Blocking Read¶
If the file is opened with O_NONBLOCK, do not sleep.
Example:
This matches standard Linux non-blocking I/O behavior.
Step 6 - Add poll Support¶
Include the required header:
Add a poll callback:
static __poll_t mygpio_poll(struct file *file, poll_table *wait)
{
struct mygpio_dev *mydev = file->private_data;
__poll_t mask = 0;
poll_wait(file, &mydev->read_queue, wait);
if (mydev->event_pending)
mask |= POLLIN | POLLRDNORM;
return mask;
}
Step 7 - Register poll in file_operations¶
static const struct file_operations mygpio_fops = {
.owner = THIS_MODULE,
.open = mygpio_open,
.release = mygpio_release,
.read = mygpio_read,
.write = mygpio_write,
.poll = mygpio_poll,
};
Step 8 - Build and Load¶
Step 9 - Test Blocking Read¶
Run:
Expected behavior:
- the command blocks
- pressing or releasing the button wakes the reader
- one event line is returned
Step 10 - Test Non-Blocking Read¶
Use a user-space program that opens the device with O_NONBLOCK.
Expected behavior:
- no event available →
read()returns-EAGAIN - event available →
read()returns data immediately
Step 11 - Test poll()¶
Example user-space flow:
Expected behavior:
poll()blocks until an event occurs- button IRQ wakes
poll() read()consumes the event data
Step 12 - Optional Timeout Test¶
Example:
Expected behavior:
- event occurs within 5 seconds →
poll()returns ready - no event within 5 seconds → timeout
Result¶
At the end of this lab, the driver supports:
- blocking I/O
- non-blocking I/O
- event-driven I/O
This is the core Linux model for asynchronous user-space notification.