2b8dd96a5c
Consolidate ~30 absorbed base patches into surviving carriers. Add new init service files, driver sources, and network/storage modules for the base recipe. Move absorbed patches to local/patches/base/absorbed/.
245 lines
7.6 KiB
Diff
245 lines
7.6 KiB
Diff
--- a/drivers/inputd/src/main.rs
|
|
+++ b/drivers/inputd/src/main.rs
|
|
@@ -18,7 +18,7 @@
|
|
use std::ops::ControlFlow;
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
|
|
|
-use inputd::{ControlEvent, VtEvent, VtEventKind};
|
|
+use inputd::{ControlEvent, HotplugEventHeader, VtEvent, VtEventKind};
|
|
|
|
use libredox::errno::ESTALE;
|
|
use redox_scheme::scheme::SchemeSync;
|
|
@@ -49,6 +49,17 @@
|
|
notified: bool,
|
|
vt: usize,
|
|
},
|
|
+ DeviceConsumer {
|
|
+ device_name: String,
|
|
+ events: EventFlags,
|
|
+ pending: Vec<u8>,
|
|
+ notified: bool,
|
|
+ },
|
|
+ HotplugEvents {
|
|
+ events: EventFlags,
|
|
+ pending: Vec<u8>,
|
|
+ notified: bool,
|
|
+ },
|
|
Display {
|
|
events: EventFlags,
|
|
pending: Vec<VtEvent>,
|
|
@@ -89,6 +100,9 @@
|
|
"control",
|
|
];
|
|
|
|
+const DEVICE_ADD: u32 = 1;
|
|
+const DEVICE_REMOVE: u32 = 2;
|
|
+
|
|
enum ProducerKind {
|
|
Legacy,
|
|
Named(String),
|
|
@@ -116,7 +130,7 @@
|
|
}
|
|
|
|
fn register_named_producer(&mut self, name: &str) -> syscall::Result<Handle> {
|
|
- if name.is_empty() || RESERVED_DEVICE_NAMES.contains(&name) {
|
|
+ if name.is_empty() || name.contains('/') || RESERVED_DEVICE_NAMES.contains(&name) {
|
|
return Err(SysError::new(EINVAL));
|
|
}
|
|
|
|
@@ -126,9 +140,55 @@
|
|
|
|
let device_id = self.next_device_id.fetch_add(1, Ordering::SeqCst) as u32;
|
|
self.devices.insert(name.to_owned(), device_id);
|
|
+ self.queue_hotplug_event(DEVICE_ADD, device_id, name)?;
|
|
Ok(Handle::NamedProducer {
|
|
name: name.to_owned(),
|
|
})
|
|
+ }
|
|
+
|
|
+ fn drain_pending_bytes(pending: &mut Vec<u8>, buf: &mut [u8]) -> usize {
|
|
+ let copy = core::cmp::min(pending.len(), buf.len());
|
|
+
|
|
+ for (i, byte) in pending.drain(..copy).enumerate() {
|
|
+ buf[i] = byte;
|
|
+ }
|
|
+
|
|
+ copy
|
|
+ }
|
|
+
|
|
+ fn queue_hotplug_event(
|
|
+ &mut self,
|
|
+ kind: u32,
|
|
+ device_id: u32,
|
|
+ name: &str,
|
|
+ ) -> syscall::Result<()> {
|
|
+ let name_len = u32::try_from(name.len()).map_err(|_| SysError::new(EINVAL))?;
|
|
+ let header = HotplugEventHeader {
|
|
+ kind,
|
|
+ device_id,
|
|
+ name_len,
|
|
+ _reserved: 0,
|
|
+ };
|
|
+ let header_bytes = unsafe {
|
|
+ core::slice::from_raw_parts(
|
|
+ (&header as *const HotplugEventHeader).cast::<u8>(),
|
|
+ size_of::<HotplugEventHeader>(),
|
|
+ )
|
|
+ };
|
|
+
|
|
+ for handle in self.handles.values_mut() {
|
|
+ if let Handle::HotplugEvents {
|
|
+ pending, notified, ..
|
|
+ } = handle
|
|
+ {
|
|
+ pending.extend_from_slice(header_bytes);
|
|
+ pending.extend_from_slice(name.as_bytes());
|
|
+ *notified = false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ self.has_new_events = true;
|
|
+ Ok(())
|
|
}
|
|
|
|
fn route_legacy_consumer_events(&mut self, buf: &[u8]) {
|
|
@@ -150,9 +210,21 @@
|
|
}
|
|
}
|
|
|
|
- fn route_named_producer_events(&mut self, _name: &str, _buf: &[u8]) {
|
|
- // DeviceConsumer routing is added in a follow-up patch. Named producers already share the
|
|
- // legacy consumer path, so existing callers continue to receive these events.
|
|
+ fn route_named_producer_events(&mut self, name: &str, buf: &[u8]) {
|
|
+ for handle in self.handles.values_mut() {
|
|
+ match handle {
|
|
+ Handle::DeviceConsumer {
|
|
+ device_name,
|
|
+ pending,
|
|
+ notified,
|
|
+ ..
|
|
+ } if device_name == name => {
|
|
+ pending.extend_from_slice(buf);
|
|
+ *notified = false;
|
|
+ }
|
|
+ _ => continue,
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
fn switch_vt(&mut self, new_active: usize) {
|
|
@@ -319,7 +391,24 @@
|
|
is_earlyfb: command == "handle_early",
|
|
}
|
|
}
|
|
+ "events" if path_parts.next().is_none() => Handle::HotplugEvents {
|
|
+ events: EventFlags::empty(),
|
|
+ pending: Vec::new(),
|
|
+ notified: false,
|
|
+ },
|
|
"control" => Handle::Control,
|
|
+ device_name
|
|
+ if !device_name.is_empty()
|
|
+ && !RESERVED_DEVICE_NAMES.contains(&device_name)
|
|
+ && path_parts.next().is_none() =>
|
|
+ {
|
|
+ Handle::DeviceConsumer {
|
|
+ device_name: device_name.to_owned(),
|
|
+ events: EventFlags::empty(),
|
|
+ pending: Vec::new(),
|
|
+ notified: false,
|
|
+ }
|
|
+ }
|
|
|
|
_ => {
|
|
log::error!("invalid path '{path}'");
|
|
@@ -372,13 +461,11 @@
|
|
return Err(SysError::new(ESTALE));
|
|
}
|
|
|
|
- let copy = core::cmp::min(pending.len(), buf.len());
|
|
-
|
|
- for (i, byte) in pending.drain(..copy).enumerate() {
|
|
- buf[i] = byte;
|
|
- }
|
|
-
|
|
- Ok(copy)
|
|
+ Ok(Self::drain_pending_bytes(pending, buf))
|
|
+ }
|
|
+
|
|
+ Handle::DeviceConsumer { pending, .. } | Handle::HotplugEvents { pending, .. } => {
|
|
+ Ok(Self::drain_pending_bytes(pending, buf))
|
|
}
|
|
|
|
Handle::Display { pending, .. } => {
|
|
@@ -443,6 +530,10 @@
|
|
|
|
Handle::Consumer { .. } => {
|
|
log::error!("consumer tried to write");
|
|
+ return Err(SysError::new(EINVAL));
|
|
+ }
|
|
+ Handle::DeviceConsumer { .. } | Handle::HotplugEvents { .. } => {
|
|
+ log::error!("consumer or hotplug handle tried to write");
|
|
return Err(SysError::new(EINVAL));
|
|
}
|
|
Handle::Display { .. } => {
|
|
@@ -531,6 +622,16 @@
|
|
ref mut events,
|
|
ref mut notified,
|
|
..
|
|
+ }
|
|
+ | Handle::DeviceConsumer {
|
|
+ ref mut events,
|
|
+ ref mut notified,
|
|
+ ..
|
|
+ }
|
|
+ | Handle::HotplugEvents {
|
|
+ ref mut events,
|
|
+ ref mut notified,
|
|
+ ..
|
|
} => {
|
|
*events = flags;
|
|
*notified = false;
|
|
@@ -561,7 +662,12 @@
|
|
|
|
match handle {
|
|
Handle::NamedProducer { name } => {
|
|
- self.devices.remove(&name);
|
|
+ if let Some(device_id) = self.devices.remove(&name) {
|
|
+ self.queue_hotplug_event(DEVICE_REMOVE, device_id, &name)
|
|
+ .unwrap_or_else(|err| {
|
|
+ log::error!("failed to queue removal hotplug event for {name}: {err}");
|
|
+ });
|
|
+ }
|
|
}
|
|
Handle::Consumer { vt, .. } => {
|
|
self.vts.remove(&vt);
|
|
@@ -639,6 +745,28 @@
|
|
|
|
*notified = true;
|
|
}
|
|
+ Handle::DeviceConsumer {
|
|
+ events,
|
|
+ pending,
|
|
+ ref mut notified,
|
|
+ ..
|
|
+ }
|
|
+ | Handle::HotplugEvents {
|
|
+ events,
|
|
+ pending,
|
|
+ ref mut notified,
|
|
+ } => {
|
|
+ if pending.is_empty() || *notified || !events.contains(EventFlags::EVENT_READ) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ socket_file.write_response(
|
|
+ Response::post_fevent(*id, EventFlags::EVENT_READ.bits()),
|
|
+ SignalBehavior::Restart,
|
|
+ )?;
|
|
+
|
|
+ *notified = true;
|
|
+ }
|
|
_ => {}
|
|
}
|
|
}
|