drivers/input/evdev.c
Source file repositories/reference/linux-study-clean/drivers/input/evdev.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/input/evdev.c- Extension
.c- Size
- 33168 bytes
- Lines
- 1447
- Domain
- Driver Families
- Bucket
- drivers/input
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/poll.hlinux/sched.hlinux/slab.hlinux/vmalloc.hlinux/mm.hlinux/module.hlinux/init.hlinux/input/mt.hlinux/major.hlinux/device.hlinux/cdev.hinput-compat.h
Detected Declarations
struct evdevstruct evdev_clientfunction evdev_get_mask_cntfunction __evdev_is_filteredfunction __evdev_flush_queuefunction __evdev_queue_syn_droppedfunction evdev_queue_syn_droppedfunction evdev_set_clk_typefunction __pass_eventfunction evdev_pass_valuesfunction evdev_eventsfunction evdev_fasyncfunction evdev_freefunction devicefunction evdev_ungrabfunction evdev_attach_clientfunction evdev_detach_clientfunction evdev_open_devicefunction evdev_close_devicefunction evdev_hangupfunction evdev_releasefunction evdev_compute_buffer_sizefunction evdev_openfunction evdev_writefunction evdev_fetch_next_eventfunction evdev_readfunction evdev_pollfunction bits_to_userfunction bits_from_userfunction bits_to_userfunction bits_from_userfunction bits_to_userfunction bits_from_userfunction str_to_userfunction handle_eviocgbitfunction evdev_handle_get_keycodefunction evdev_handle_get_keycode_v2function evdev_handle_set_keycodefunction evdev_handle_set_keycode_v2function evdev_handle_get_valfunction evdev_handle_mt_requestfunction evdev_revokefunction evdev_set_maskfunction evdev_get_maskfunction evdev_do_ioctlfunction evdev_ioctl_handlerfunction evdev_ioctlfunction evdev_ioctl_compat
Annotated Snippet
static const struct file_operations evdev_fops = {
.owner = THIS_MODULE,
.read = evdev_read,
.write = evdev_write,
.poll = evdev_poll,
.open = evdev_open,
.release = evdev_release,
.unlocked_ioctl = evdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = evdev_ioctl_compat,
#endif
.fasync = evdev_fasync,
};
/*
* Mark device non-existent. This disables writes, ioctls and
* prevents new users from opening the device. Already posted
* blocking reads will stay, however new ones will fail.
*/
static void evdev_mark_dead(struct evdev *evdev)
{
mutex_lock(&evdev->mutex);
evdev->exist = false;
mutex_unlock(&evdev->mutex);
}
static void evdev_cleanup(struct evdev *evdev)
{
struct input_handle *handle = &evdev->handle;
evdev_mark_dead(evdev);
evdev_hangup(evdev);
/* evdev is marked dead so no one else accesses evdev->open */
if (evdev->open) {
input_flush_device(handle, NULL);
input_close_device(handle);
}
}
/*
* Create new evdev device. Note that input core serializes calls
* to connect and disconnect.
*/
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
int minor;
int dev_no;
int error;
minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
if (minor < 0) {
error = minor;
pr_err("failed to reserve new minor: %d\n", error);
return error;
}
evdev = kzalloc_obj(struct evdev);
if (!evdev) {
error = -ENOMEM;
goto err_free_minor;
}
INIT_LIST_HEAD(&evdev->client_list);
spin_lock_init(&evdev->client_lock);
mutex_init(&evdev->mutex);
evdev->exist = true;
dev_no = minor;
/* Normalize device number if it falls into legacy range */
if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
dev_no -= EVDEV_MINOR_BASE;
dev_set_name(&evdev->dev, "event%d", dev_no);
evdev->handle.dev = input_get_device(dev);
evdev->handle.name = dev_name(&evdev->dev);
evdev->handle.handler = handler;
evdev->handle.private = evdev;
evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
evdev->dev.release = evdev_free;
device_initialize(&evdev->dev);
error = input_register_handle(&evdev->handle);
if (error)
goto err_free_evdev;
Annotation
- Immediate include surface: `linux/poll.h`, `linux/sched.h`, `linux/slab.h`, `linux/vmalloc.h`, `linux/mm.h`, `linux/module.h`, `linux/init.h`, `linux/input/mt.h`.
- Detected declarations: `struct evdev`, `struct evdev_client`, `function evdev_get_mask_cnt`, `function __evdev_is_filtered`, `function __evdev_flush_queue`, `function __evdev_queue_syn_dropped`, `function evdev_queue_syn_dropped`, `function evdev_set_clk_type`, `function __pass_event`, `function evdev_pass_values`.
- Atlas domain: Driver Families / drivers/input.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.