starnix_modules_mmcblk_stub/
lib.rs1#![cfg_attr(test, recursion_limit = "256")]
6
7use starnix_core::device::DeviceMode;
8use starnix_core::device::kobject::DeviceMetadata;
9use starnix_core::fs::sysfs::{
10 BlockDeviceInfo, build_block_device_directory, build_device_directory,
11};
12use starnix_core::task::{CurrentTask, Kernel};
13use starnix_core::vfs::pseudo::stub_empty_file::StubEmptyFile;
14use starnix_core::vfs::{FileOps, FsString, NamespaceNode};
15use starnix_logging::{bug_ref, track_stub};
16use starnix_uapi::device_id::DeviceId;
17use starnix_uapi::errno;
18use starnix_uapi::errors::Errno;
19use starnix_uapi::file_mode::mode;
20use starnix_uapi::open_flags::OpenFlags;
21use std::sync::Arc;
22
23struct MmcBlockDevice;
24
25impl BlockDeviceInfo for MmcBlockDevice {
26 fn size(&self) -> Result<usize, Errno> {
27 track_stub!(TODO("https://fxbug.dev/488067251"), "mmcblk query size");
28 Err(errno!(ENOTSUP))
29 }
30}
31
32pub fn mmcblk_stub_device_init(kernel: &Kernel) -> Result<(), Errno> {
34 let registry = &kernel.device_registry;
35 let objects = ®istry.objects;
36
37 let mmc0 = registry.add_numberless_device(
40 "mmc0".into(),
41 None,
42 objects.get_or_create_class("mmc_host".into()),
43 build_device_directory,
44 );
45 let mmc_card = registry.add_bus_device(
46 "mmc0:0001".into(),
47 Some(mmc0),
48 objects.get_or_create_bus("mmc".into()),
49 |device, dir| {
50 build_device_directory(device, dir);
51 for name in ["fwrev", "hwrev", "life_time", "manfid", "pre_eol_info", "serial"] {
52 dir.entry(
53 name,
54 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
55 mode!(IFREG, 0o444),
56 );
57 }
58 },
59 );
60
61 let name = FsString::from("mmcblk0");
62 let device = Arc::new(MmcBlockDevice);
63 let device_weak = Arc::downgrade(&device);
64 registry.add_device_with_dir(
65 kernel,
66 name.as_ref(),
67 DeviceMetadata::new(name.clone(), DeviceId::MMCBLK0, DeviceMode::Block),
68 Some(mmc_card),
69 objects.block_class(),
70 |device, dir| build_block_device_directory(device, device_weak, dir),
71 move |_current_task: &CurrentTask,
72 _id: DeviceId,
73 _node: &NamespaceNode,
74 _flags: OpenFlags|
75 -> Result<Box<dyn FileOps>, Errno> {
76 let _keep_alive = &device;
79 track_stub!(TODO("https://fxbug.dev/488067251"), "mmcblk open device");
80 Err(errno!(ENOTSUP))
81 },
82 );
83 Ok(())
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use starnix_core::testing::{anon_test_file, spawn_kernel_and_run};
90 use starnix_core::vfs::VecOutputBuffer;
91
92 #[::fuchsia::test]
93 async fn mmcblk_stub_device_init_registers_host_card_and_block_devices() {
94 spawn_kernel_and_run(async |current_task| {
95 let kernel = current_task.kernel();
96 mmcblk_stub_device_init(kernel).expect("mmcblk_stub_device_init should succeed");
97
98 let root = &kernel.device_registry.objects.root;
99 assert!(root.lookup("class/mmc_host/mmc0".into()).is_some());
100 assert!(root.lookup("bus/mmc/devices/mmc0:0001".into()).is_some());
101 assert!(root.lookup("block/mmcblk0".into()).is_some());
102 assert!(root.lookup("class/block/mmcblk0".into()).is_some());
103 assert!(root.lookup("devices/virtual/mmc_host/mmc0/uevent".into()).is_some());
104 assert!(
105 root.lookup("devices/virtual/mmc_host/mmc0/mmc0:0001/life_time".into()).is_some()
106 );
107 assert!(
108 root.lookup("devices/virtual/mmc_host/mmc0/mmc0:0001/block/mmcblk0/holders".into())
109 .is_some()
110 );
111
112 let size_node = root
113 .lookup("devices/virtual/mmc_host/mmc0/mmc0:0001/block/mmcblk0/size".into())
114 .expect("size node should exist");
115 let file_ops = size_node.create_file_ops(current_task, OpenFlags::RDONLY).unwrap();
116 let file = anon_test_file(current_task, file_ops, OpenFlags::RDONLY);
117 let mut buf = VecOutputBuffer::new(10);
118 assert_eq!(file.read(current_task, &mut buf).unwrap_err(), errno!(ENOTSUP));
119 })
120 .await;
121 }
122}