mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:18:11 +00:00
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.
This commit is contained in:
parent
b60e19fd34
commit
b1ca39411b
7 changed files with 151 additions and 0 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue