diff options
author | Liav A <liavalb@gmail.com> | 2021-12-20 11:10:35 +0200 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-01-23 00:38:02 +0000 |
commit | b1ca39411b42b4164def6bf6f4e138e5ca7cffb0 (patch) | |
tree | 9ee7951e38dd4e5b8c3604e5bed2130c8fa6a584 /Kernel/Devices/DeviceManagement.cpp | |
parent | b60e19fd3406dec707c4933d840286526e4058d1 (diff) | |
download | serenity-b1ca39411b42b4164def6bf6f4e138e5ca7cffb0.zip |
Kernel/Devices: Introduce the Device Control Device
This device will assist userspace to manage hotplug events.
A userspace application reads a DeviceEvent entry until the return value
is zero which indicates no events that are queued and waiting for
processing.
Trying to read with a buffer smaller than sizeof(DeviceEvent) results in
EOVERFLOW.
For now, there's no ioctl mechanism for this device but in the future an
acknowledgement mechanism can be implemented via ioctl(2) interface.
Diffstat (limited to 'Kernel/Devices/DeviceManagement.cpp')
-rw-r--r-- | Kernel/Devices/DeviceManagement.cpp | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/Kernel/Devices/DeviceManagement.cpp b/Kernel/Devices/DeviceManagement.cpp index 5f68d1cfb4..3315c80e21 100644 --- a/Kernel/Devices/DeviceManagement.cpp +++ b/Kernel/Devices/DeviceManagement.cpp @@ -37,6 +37,11 @@ UNMAP_AFTER_INIT void DeviceManagement::attach_null_device(NullDevice const& dev m_null_device = device; } +UNMAP_AFTER_INIT void DeviceManagement::attach_device_control_device(DeviceControlDevice const& device) +{ + m_device_control_device = device; +} + DeviceManagement& DeviceManagement::the() { return *s_the; @@ -52,6 +57,14 @@ Device* DeviceManagement::get_device(MajorNumber major, MinorNumber minor) }); } +Optional<DeviceEvent> DeviceManagement::dequeue_top_device_event(Badge<DeviceControlDevice>) +{ + SpinlockLocker locker(m_event_queue_lock); + if (m_event_queue.is_empty()) + return {}; + return m_event_queue.dequeue(); +} + void DeviceManagement::before_device_removal(Badge<Device>, Device& device) { u64 device_id = encoded_device(device.major(), device.minor()); @@ -59,6 +72,14 @@ void DeviceManagement::before_device_removal(Badge<Device>, Device& device) VERIFY(map.contains(device_id)); map.remove(encoded_device(device.major(), device.minor())); }); + + { + DeviceEvent event { DeviceEvent::State::Removed, device.is_block_device(), device.major().value(), device.minor().value() }; + SpinlockLocker locker(m_event_queue_lock); + m_event_queue.enqueue(event); + } + if (m_device_control_device) + m_device_control_device->evaluate_block_conditions(); } void DeviceManagement::after_inserting_device(Badge<Device>, Device& device) @@ -75,6 +96,14 @@ void DeviceManagement::after_inserting_device(Badge<Device>, Device& device) VERIFY_NOT_REACHED(); } }); + + { + DeviceEvent event { DeviceEvent::State::Inserted, device.is_block_device(), device.major().value(), device.minor().value() }; + SpinlockLocker locker(m_event_queue_lock); + m_event_queue.enqueue(event); + } + if (m_device_control_device) + m_device_control_device->evaluate_block_conditions(); } void DeviceManagement::for_each(Function<void(Device&)> callback) |