1use crate::device::kobject::{Class, Device, DeviceMetadata, UEventAction, UEventContext};
6use crate::device::kobject_store::KObjectStore;
7use crate::fs::devtmpfs::{devtmpfs_create_device, devtmpfs_remove_path};
8use crate::fs::sysfs::build_device_directory;
9use crate::task::{CurrentTask, Kernel, register_delayed_release};
10use crate::vfs::pseudo::simple_directory::SimpleDirectoryMutator;
11use crate::vfs::{FileOps, FsStr, FsString, NamespaceNode};
12use starnix_lifecycle::{ObjectReleaser, ReleaserAction};
13use starnix_logging::log_error;
14use starnix_sync::{DeviceRegistryStateLevel, LockDepGuard, LockDepMutex, MappedLockDepGuard};
15use starnix_types::ownership::{Releasable, ReleaseGuard};
16use starnix_uapi::as_any::AsAny;
17use starnix_uapi::device_id::{DYN_MAJOR_RANGE, DeviceId, MISC_DYNANIC_MINOR_RANGE, MISC_MAJOR};
18use starnix_uapi::error;
19use starnix_uapi::errors::Errno;
20use starnix_uapi::open_flags::OpenFlags;
21use std::collections::btree_map::{BTreeMap, Entry};
22use std::ops::{Deref, Range};
23use std::sync::Arc;
24
25use dyn_clone::{DynClone, clone_trait_object};
26
27const CHRDEV_MINOR_MAX: u32 = 256;
28const BLKDEV_MINOR_MAX: u32 = 2u32.pow(20);
29
30#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
32pub enum DeviceMode {
33 Char,
35
36 Block,
38}
39
40impl DeviceMode {
41 fn minor_count(&self) -> u32 {
43 match self {
44 Self::Char => CHRDEV_MINOR_MAX,
45 Self::Block => BLKDEV_MINOR_MAX,
46 }
47 }
48
49 pub fn minor_range(&self) -> Range<u32> {
51 0..self.minor_count()
52 }
53}
54
55pub trait DeviceOps: DynClone + Send + Sync + AsAny + 'static {
56 fn open(
61 &self,
62 current_task: &CurrentTask,
63 devt: DeviceId,
64 node: &NamespaceNode,
65 flags: OpenFlags,
66 ) -> Result<Box<dyn FileOps>, Errno>;
67}
68
69clone_trait_object!(DeviceOps);
70
71impl<F> DeviceOps for F
74where
75 F: Clone
76 + Send
77 + Sync
78 + Clone
79 + Fn(&CurrentTask, DeviceId, &NamespaceNode, OpenFlags) -> Result<Box<dyn FileOps>, Errno>
80 + 'static,
81{
82 fn open(
83 &self,
84 current_task: &CurrentTask,
85 id: DeviceId,
86 node: &NamespaceNode,
87 flags: OpenFlags,
88 ) -> Result<Box<dyn FileOps>, Errno> {
89 self(current_task, id, node, flags)
90 }
91}
92
93pub fn simple_device_ops<T: Default + FileOps + 'static>(
95 _current_task: &CurrentTask,
96 _id: DeviceId,
97 _node: &NamespaceNode,
98 _flags: OpenFlags,
99) -> Result<Box<dyn FileOps>, Errno> {
100 Ok(Box::new(T::default()))
101}
102
103pub type DeviceListenerKey = u64;
106
107pub trait DeviceListener: Send + Sync {
109 fn on_device_event(&self, action: UEventAction, device: Device, context: UEventContext);
110}
111
112pub struct DeviceOpsWrapper(Box<dyn DeviceOps>);
113impl ReleaserAction<DeviceOpsWrapper> for DeviceOpsWrapper {
114 fn release(device_ops: ReleaseGuard<DeviceOpsWrapper>) {
115 register_delayed_release(device_ops);
116 }
117}
118impl Deref for DeviceOpsWrapper {
119 type Target = dyn DeviceOps;
120 fn deref(&self) -> &Self::Target {
121 self.0.deref()
122 }
123}
124pub type DeviceReleaser = ObjectReleaser<DeviceOpsWrapper, DeviceOpsWrapper>;
125pub type DeviceHandle = Arc<DeviceReleaser>;
126impl Releasable for DeviceOpsWrapper {
127 type Context<'a> = &'a CurrentTask;
128
129 fn release<'a>(self, _context: &'a CurrentTask) {}
130}
131
132struct DeviceEntry {
134 name: FsString,
138
139 ops: DeviceHandle,
141}
142
143impl DeviceEntry {
144 fn new(name: FsString, ops: impl DeviceOps) -> Self {
145 Self { name, ops: Arc::new(DeviceOpsWrapper(Box::new(ops)).into()) }
146 }
147}
148
149#[derive(Default)]
153struct RegisteredDevices {
154 majors: BTreeMap<u32, DeviceEntry>,
163
164 minors: BTreeMap<DeviceId, DeviceEntry>,
168}
169
170impl RegisteredDevices {
171 fn register_major(&mut self, major: u32, entry: DeviceEntry) -> Result<(), Errno> {
175 if let Entry::Vacant(slot) = self.majors.entry(major) {
176 slot.insert(entry);
177 Ok(())
178 } else {
179 error!(EINVAL)
180 }
181 }
182
183 fn register_minor(&mut self, devt: DeviceId, entry: DeviceEntry) {
187 self.minors.insert(devt, entry);
188 }
189
190 fn get(&self, devt: DeviceId) -> Result<DeviceHandle, Errno> {
197 if let Some(major_device) = self.majors.get(&devt.major()) {
198 Ok(Arc::clone(&major_device.ops))
199 } else if let Some(minor_device) = self.minors.get(&devt) {
200 Ok(Arc::clone(&minor_device.ops))
201 } else {
202 error!(ENODEV)
203 }
204 }
205
206 fn list_major_devices(&self) -> Vec<(u32, FsString)> {
208 self.majors.iter().map(|(major, entry)| (*major, entry.name.clone())).collect()
209 }
210
211 fn list_minor_devices(&self, range: Range<DeviceId>) -> Vec<(DeviceId, FsString)> {
213 self.minors.range(range).map(|(devt, entry)| (devt.clone(), entry.name.clone())).collect()
214 }
215}
216
217pub struct DeviceRegistry {
226 pub objects: KObjectStore,
228
229 state: LockDepMutex<DeviceRegistryState, DeviceRegistryStateLevel>,
231}
232struct DeviceRegistryState {
233 char_devices: RegisteredDevices,
235
236 block_devices: RegisteredDevices,
238
239 misc_chardev_allocator: DeviceIdAllocator,
243
244 dyn_chardev_allocator: DeviceIdAllocator,
248
249 next_anon_minor: u32,
251
252 listeners: BTreeMap<u64, Box<dyn DeviceListener>>,
257
258 next_listener_id: u64,
260
261 next_event_id: u64,
263}
264
265impl DeviceRegistry {
266 fn notify_device(&self, kernel: &Kernel, device: Device) -> Result<(), Errno> {
268 if let Some(metadata) = &device.metadata {
269 devtmpfs_create_device(kernel, metadata.clone())?;
270 self.dispatch_uevent(UEventAction::Add, device);
271 }
272 Ok(())
273 }
274
275 pub fn register_device<'a>(
322 &self,
323 kernel: &Kernel,
324 name: &FsStr,
325 metadata: DeviceMetadata,
326 class: Class,
327 dev_ops: impl DeviceOps,
328 ) -> Result<Device, Errno> {
329 self.register_device_with_dir(
330 kernel,
331 name,
332 metadata,
333 class,
334 build_device_directory,
335 dev_ops,
336 )
337 }
338
339 pub fn register_device_with_dir<'a>(
343 &self,
344 kernel: &Kernel,
345 name: &FsStr,
346 metadata: DeviceMetadata,
347 class: Class,
348 build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator),
349 dev_ops: impl DeviceOps,
350 ) -> Result<Device, Errno> {
351 let entry = DeviceEntry::new(name.into(), dev_ops);
352 self.devices(metadata.mode).register_minor(metadata.devt, entry);
353 self.add_device(kernel, name, metadata, class, build_directory)
354 }
355
356 pub fn register_misc_device<'a>(
364 &self,
365 kernel: &Kernel,
366 name: &FsStr,
367 dev_ops: impl DeviceOps,
368 ) -> Result<Device, Errno> {
369 let devt = self.state.lock().misc_chardev_allocator.allocate()?;
370 let metadata = DeviceMetadata::new(name.into(), devt, DeviceMode::Char);
371 Ok(self.register_device(kernel, name, metadata, self.objects.misc_class(), dev_ops)?)
372 }
373
374 pub fn register_dyn_device<'a>(
385 &self,
386 kernel: &Kernel,
387 name: &FsStr,
388 class: Class,
389 dev_ops: impl DeviceOps,
390 ) -> Result<Device, Errno> {
391 self.register_dyn_device_with_dir(kernel, name, class, build_device_directory, dev_ops)
392 }
393
394 pub fn register_dyn_device_with_dir<'a>(
398 &self,
399 kernel: &Kernel,
400 name: &FsStr,
401 class: Class,
402 build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator),
403 dev_ops: impl DeviceOps,
404 ) -> Result<Device, Errno> {
405 self.register_dyn_device_with_devname(kernel, name, name, class, build_directory, dev_ops)
406 }
407
408 pub fn register_dyn_device_with_devname<'a>(
419 &self,
420 kernel: &Kernel,
421 name: &FsStr,
422 devname: &FsStr,
423 class: Class,
424 build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator),
425 dev_ops: impl DeviceOps,
426 ) -> Result<Device, Errno> {
427 let devt = self.state.lock().dyn_chardev_allocator.allocate()?;
428 let metadata = DeviceMetadata::new(devname.into(), devt, DeviceMode::Char);
429 Ok(self.register_device_with_dir(
430 kernel,
431 name,
432 metadata,
433 class,
434 build_directory,
435 dev_ops,
436 )?)
437 }
438
439 pub fn register_silent_dyn_device<'a>(
446 &self,
447 name: &FsStr,
448 dev_ops: impl DeviceOps,
449 ) -> Result<DeviceMetadata, Errno> {
450 let devt = self.state.lock().dyn_chardev_allocator.allocate()?;
451 let metadata = DeviceMetadata::new(name.into(), devt, DeviceMode::Char);
452 let entry = DeviceEntry::new(name.into(), dev_ops);
453 self.devices(metadata.mode).register_minor(metadata.devt, entry);
454 Ok(metadata)
455 }
456
457 pub fn add_device<'a>(
465 &self,
466 kernel: &Kernel,
467 name: &FsStr,
468 metadata: DeviceMetadata,
469 class: Class,
470 build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator),
471 ) -> Result<Device, Errno> {
472 self.devices(metadata.mode).get(metadata.devt).expect("device is registered");
473 let device = self.objects.create_device(name, Some(metadata), class, build_directory);
474
475 self.notify_device(kernel, device.clone())?;
476 Ok(device)
477 }
478
479 pub fn add_net_device(&self, name: &FsStr) -> Device {
491 self.objects.create_device(name, None, self.objects.net_class(), build_device_directory)
492 }
493
494 pub fn remove_net_device(&self, device: Device) {
498 assert!(device.metadata.is_none());
499 self.objects.remove(&device);
500 }
501
502 pub fn add_numberless_device(
509 &self,
510 name: &FsStr,
511 class: Class,
512 build_directory: impl FnOnce(&Device, &SimpleDirectoryMutator),
513 ) -> Device {
514 self.objects.create_device(name, None, class, build_directory)
515 }
516
517 pub fn remove_device(&self, current_task: &CurrentTask, device: Device) {
522 if let Some(metadata) = &device.metadata {
523 self.dispatch_uevent(UEventAction::Remove, device.clone());
524
525 if let Err(err) = devtmpfs_remove_path(current_task, metadata.devname.as_ref()) {
526 log_error!("Cannot remove device {:?} ({:?})", device, err);
527 }
528 }
529
530 self.objects.remove(&device);
531 }
532
533 pub fn list_major_devices(&self, mode: DeviceMode) -> Vec<(u32, FsString)> {
536 self.devices(mode).list_major_devices()
537 }
538
539 pub fn list_minor_devices(
541 &self,
542 mode: DeviceMode,
543 range: Range<DeviceId>,
544 ) -> Vec<(DeviceId, FsString)> {
545 self.devices(mode).list_minor_devices(range)
546 }
547
548 fn devices<'a>(&'a self, mode: DeviceMode) -> MappedLockDepGuard<'a, RegisteredDevices> {
550 LockDepGuard::map(self.state.lock(), |state| match mode {
551 DeviceMode::Char => &mut state.char_devices,
552 DeviceMode::Block => &mut state.block_devices,
553 })
554 }
555
556 pub fn register_major<'a>(
562 &self,
563 name: FsString,
564 mode: DeviceMode,
565 major: u32,
566 dev_ops: impl DeviceOps,
567 ) -> Result<(), Errno> {
568 let entry = DeviceEntry::new(name, dev_ops);
569 self.devices(mode).register_major(major, entry)
570 }
571
572 pub fn next_anonymous_dev_id<'a>(&self) -> DeviceId {
574 let mut state = self.state.lock();
575 let id = DeviceId::new(0, state.next_anon_minor);
576 state.next_anon_minor += 1;
577 id
578 }
579
580 pub fn register_listener<'a>(
584 &self,
585 listener: impl DeviceListener + 'static,
586 ) -> DeviceListenerKey {
587 let mut state = self.state.lock();
588 let key = state.next_listener_id;
589 state.next_listener_id += 1;
590 state.listeners.insert(key, Box::new(listener));
591 key
592 }
593
594 pub fn unregister_listener<'a>(&self, key: &DeviceListenerKey) {
596 self.state.lock().listeners.remove(key);
597 }
598
599 pub fn dispatch_uevent<'a>(&self, action: UEventAction, device: Device) {
601 let mut state = self.state.lock();
602 let event_id = state.next_event_id;
603 state.next_event_id += 1;
604 let context = UEventContext { seqnum: event_id };
605 for listener in state.listeners.values() {
606 listener.on_device_event(action, device.clone(), context);
607 }
608 }
609
610 pub fn open_device(
614 &self,
615 current_task: &CurrentTask,
616 node: &NamespaceNode,
617 flags: OpenFlags,
618 devt: DeviceId,
619 mode: DeviceMode,
620 ) -> Result<Box<dyn FileOps>, Errno> {
621 let dev_ops = self.devices(mode).get(devt)?;
622 dev_ops.open(current_task, devt, node, flags)
623 }
624
625 pub fn get_device(&self, devt: DeviceId, mode: DeviceMode) -> Result<DeviceHandle, Errno> {
626 self.devices(mode).get(devt)
627 }
628}
629
630impl Default for DeviceRegistry {
631 fn default() -> Self {
632 let misc_available = vec![DeviceId::new_range(MISC_MAJOR, MISC_DYNANIC_MINOR_RANGE)];
633 let dyn_available = DYN_MAJOR_RANGE
634 .map(|major| DeviceId::new_range(major, DeviceMode::Char.minor_range()))
635 .rev()
636 .collect();
637 let state = DeviceRegistryState {
638 char_devices: Default::default(),
639 block_devices: Default::default(),
640 misc_chardev_allocator: DeviceIdAllocator::new(misc_available),
641 dyn_chardev_allocator: DeviceIdAllocator::new(dyn_available),
642 next_anon_minor: 1,
643 listeners: Default::default(),
644 next_listener_id: 0,
645 next_event_id: 0,
646 };
647 Self { objects: Default::default(), state: state.into() }
648 }
649}
650
651struct DeviceIdAllocator {
653 freelist: Vec<Range<DeviceId>>,
657}
658
659impl DeviceIdAllocator {
660 fn new(mut available: Vec<Range<DeviceId>>) -> Self {
664 available.reverse();
665 Self { freelist: available }
666 }
667
668 fn allocate(&mut self) -> Result<DeviceId, Errno> {
672 let Some(range) = self.freelist.pop() else {
673 return error!(ENOMEM);
674 };
675 let allocated = range.start;
676 if let Some(next) = allocated.next_minor() {
677 if next < range.end {
678 self.freelist.push(next..range.end);
679 }
680 }
681 Ok(allocated)
682 }
683}
684
685#[cfg(test)]
686mod tests {
687 use super::*;
688 use crate::device::mem::DevNull;
689 use crate::testing::*;
690 use crate::vfs::*;
691 use starnix_uapi::device_id::{INPUT_MAJOR, MEM_MAJOR};
692
693 #[::fuchsia::test]
694 async fn registry_fails_to_add_duplicate_device() {
695 spawn_kernel_and_run(async |_current_task| {
696 let registry = DeviceRegistry::default();
697 registry
698 .register_major(
699 "mem".into(),
700 DeviceMode::Char,
701 MEM_MAJOR,
702 simple_device_ops::<DevNull>,
703 )
704 .expect("registers once");
705 registry
706 .register_major(
707 "random".into(),
708 DeviceMode::Char,
709 123,
710 simple_device_ops::<DevNull>,
711 )
712 .expect("registers unique");
713 registry
714 .register_major(
715 "mem".into(),
716 DeviceMode::Char,
717 MEM_MAJOR,
718 simple_device_ops::<DevNull>,
719 )
720 .expect_err("fail to register duplicate");
721 })
722 .await;
723 }
724
725 #[::fuchsia::test]
726 async fn registry_opens_device() {
727 spawn_kernel_and_run(async |current_task| {
728 let kernel = current_task.kernel();
729 let registry = DeviceRegistry::default();
730 registry
731 .register_major(
732 "mem".into(),
733 DeviceMode::Char,
734 MEM_MAJOR,
735 simple_device_ops::<DevNull>,
736 )
737 .expect("registers unique");
738
739 let fs = create_testfs(&kernel);
740 let node = create_namespace_node_for_testing(&fs, PanickingFsNode);
741
742 assert!(
744 registry
745 .open_device(
746 ¤t_task,
747 &node,
748 OpenFlags::RDONLY,
749 DeviceId::NONE,
750 DeviceMode::Char
751 )
752 .is_err()
753 );
754
755 assert!(
757 registry
758 .open_device(
759 ¤t_task,
760 &node,
761 OpenFlags::RDONLY,
762 DeviceId::NULL,
763 DeviceMode::Block
764 )
765 .is_err()
766 );
767
768 let _ = registry
770 .open_device(
771 ¤t_task,
772 &node,
773 OpenFlags::RDONLY,
774 DeviceId::NULL,
775 DeviceMode::Char,
776 )
777 .expect("opens device");
778 })
779 .await;
780 }
781
782 #[::fuchsia::test]
783 async fn registry_dynamic_misc() {
784 spawn_kernel_and_run(async |current_task| {
785 let kernel = current_task.kernel();
786 fn create_test_device(
787 _current_task: &CurrentTask,
788 _id: DeviceId,
789 _node: &NamespaceNode,
790 _flags: OpenFlags,
791 ) -> Result<Box<dyn FileOps>, Errno> {
792 Ok(Box::new(PanickingFile))
793 }
794
795 let registry = &kernel.device_registry;
796 let device = registry
797 .register_dyn_device(
798 kernel,
799 "test-device".into(),
800 registry.objects.virtual_block_class(),
801 create_test_device,
802 )
803 .unwrap();
804 let devt = device.metadata.expect("has metadata").devt;
805 assert!(DYN_MAJOR_RANGE.contains(&devt.major()));
806
807 let fs = create_testfs(&kernel);
808 let node = create_namespace_node_for_testing(&fs, PanickingFsNode);
809 let _ = registry
810 .open_device(¤t_task, &node, OpenFlags::RDONLY, devt, DeviceMode::Char)
811 .expect("opens device");
812 })
813 .await;
814 }
815
816 #[::fuchsia::test]
817 async fn registery_add_class() {
818 spawn_kernel_and_run(async |current_task| {
819 let kernel = current_task.kernel();
820 let registry = &kernel.device_registry;
821 registry
822 .register_major(
823 "input".into(),
824 DeviceMode::Char,
825 INPUT_MAJOR,
826 simple_device_ops::<DevNull>,
827 )
828 .expect("can register input");
829
830 let input_class = registry
831 .objects
832 .get_or_create_class("input".into(), registry.objects.virtual_bus());
833 registry
834 .add_device(
835 kernel,
836 "mouse".into(),
837 DeviceMetadata::new(
838 "mouse".into(),
839 DeviceId::new(INPUT_MAJOR, 0),
840 DeviceMode::Char,
841 ),
842 input_class,
843 build_device_directory,
844 )
845 .expect("add_device");
846
847 assert!(registry.objects.root.lookup("class/input/mouse".into()).is_some());
848 })
849 .await;
850 }
851
852 #[::fuchsia::test]
853 async fn registry_add_bus() {
854 spawn_kernel_and_run(async |current_task| {
855 let kernel = current_task.kernel();
856 let registry = &kernel.device_registry;
857 registry
858 .register_major(
859 "input".into(),
860 DeviceMode::Char,
861 INPUT_MAJOR,
862 simple_device_ops::<DevNull>,
863 )
864 .expect("can register input");
865
866 let bus = registry.objects.get_or_create_bus("my-bus".into());
867 let class = registry.objects.get_or_create_class("my-class".into(), bus);
868 registry
869 .add_device(
870 kernel,
871 "my-device".into(),
872 DeviceMetadata::new(
873 "my-device".into(),
874 DeviceId::new(INPUT_MAJOR, 0),
875 DeviceMode::Char,
876 ),
877 class,
878 build_device_directory,
879 )
880 .expect("add_device");
881 assert!(registry.objects.root.lookup("bus/my-bus".into()).is_some());
882 assert!(registry.objects.root.lookup("devices/my-bus/my-class".into()).is_some());
883 assert!(
884 registry.objects.root.lookup("devices/my-bus/my-class/my-device".into()).is_some()
885 );
886 })
887 .await;
888 }
889
890 #[::fuchsia::test]
891 async fn registry_remove_device() {
892 spawn_kernel_and_run(async |current_task| {
893 let kernel = current_task.kernel();
894 let registry = &kernel.device_registry;
895 registry
896 .register_major(
897 "input".into(),
898 DeviceMode::Char,
899 INPUT_MAJOR,
900 simple_device_ops::<DevNull>,
901 )
902 .expect("can register input");
903
904 let pci_bus = registry.objects.get_or_create_bus("pci".into());
905 let input_class = registry.objects.get_or_create_class("input".into(), pci_bus);
906 let mouse_dev = registry
907 .add_device(
908 kernel,
909 "mouse".into(),
910 DeviceMetadata::new(
911 "mouse".into(),
912 DeviceId::new(INPUT_MAJOR, 0),
913 DeviceMode::Char,
914 ),
915 input_class.clone(),
916 build_device_directory,
917 )
918 .expect("add_device");
919
920 assert!(registry.objects.root.lookup("bus/pci/devices/mouse".into()).is_some());
921 assert!(registry.objects.root.lookup("devices/pci/input/mouse".into()).is_some());
922 assert!(registry.objects.root.lookup("class/input/mouse".into()).is_some());
923
924 registry.remove_device(¤t_task, mouse_dev);
925
926 assert!(registry.objects.root.lookup("bus/pci/devices/mouse".into()).is_none());
927 assert!(registry.objects.root.lookup("devices/pci/input/mouse".into()).is_none());
928 assert!(registry.objects.root.lookup("class/input/mouse".into()).is_none());
929 })
930 .await;
931 }
932
933 #[::fuchsia::test]
934 async fn registry_add_and_remove_numberless_device() {
935 spawn_kernel_and_run(async |current_task| {
936 let kernel = current_task.kernel();
937 let registry = &kernel.device_registry;
938
939 let cooling_device = registry.add_numberless_device(
940 "cooling_device0".into(),
941 registry.objects.virtual_thermal_class(),
942 build_device_directory,
943 );
944
945 assert!(registry.objects.root.lookup("class/thermal/cooling_device0".into()).is_some());
946 assert!(
947 registry
948 .objects
949 .root
950 .lookup("devices/virtual/thermal/cooling_device0".into())
951 .is_some()
952 );
953
954 registry.remove_device(¤t_task, cooling_device);
955
956 assert!(registry.objects.root.lookup("class/thermal/cooling_device0".into()).is_none());
957 assert!(
958 registry
959 .objects
960 .root
961 .lookup("devices/virtual/thermal/cooling_device0".into())
962 .is_none()
963 );
964 })
965 .await;
966 }
967}