1 use alloc::sync::Arc; 2 3 use crate::{kerror, syscall::SystemError}; 4 5 use super::{ 6 device::{device_manager, mkdev, Device, DeviceNumber, IdTable, CHARDEVS, DEVMAP}, 7 map::{ 8 kobj_map, kobj_unmap, DeviceStruct, DEV_MAJOR_DYN_END, DEV_MAJOR_DYN_EXT_END, 9 DEV_MAJOR_DYN_EXT_START, DEV_MAJOR_HASH_SIZE, DEV_MAJOR_MAX, MINOR_MASK, 10 }, 11 }; 12 13 pub trait CharDevice: Device { 14 /// Notice buffer对应设备按字节划分,使用u8类型 15 /// Notice offset应该从0开始计数 16 17 /// @brief: 从设备的第offset个字节开始,读取len个byte,存放到buf中 18 /// @parameter offset: 起始字节偏移量 19 /// @parameter len: 读取字节的数量 20 /// @parameter buf: 目标数组 21 /// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度 22 fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError>; 23 24 /// @brief: 从设备的第offset个字节开始,把buf数组的len个byte,写入到设备中 25 /// @parameter offset: 起始字节偏移量 26 /// @parameter len: 读取字节的数量 27 /// @parameter buf: 目标数组 28 /// @return: 如果操作成功,返回操作的长度(单位是字节);否则返回错误码;如果操作异常,但是并没有检查出什么错误,将返回已操作的长度 29 fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError>; 30 31 /// @brief: 同步信息,把所有的dirty数据写回设备 - 待实现 32 fn sync(&self) -> Result<(), SystemError>; 33 } 34 35 /// @brief 字符设备框架函数集 36 pub struct CharDevOps; 37 38 impl CharDevOps { 39 /// @brief: 主设备号转下标 40 /// @parameter: major: 主设备号 41 /// @return: 返回下标 42 #[allow(dead_code)] 43 fn major_to_index(major: usize) -> usize { 44 return major % DEV_MAJOR_HASH_SIZE; 45 } 46 47 /// @brief: 动态获取主设备号 48 /// @parameter: None 49 /// @return: 如果成功,返回主设备号,否则,返回错误码 50 #[allow(dead_code)] 51 fn find_dynamic_major() -> Result<usize, SystemError> { 52 let chardevs = CHARDEVS.lock(); 53 // 寻找主设备号为234~255的设备 54 for index in (DEV_MAJOR_DYN_END..DEV_MAJOR_HASH_SIZE).rev() { 55 if let Some(item) = chardevs.get(index) { 56 if item.is_empty() { 57 return Ok(index); // 返回可用的主设备号 58 } 59 } 60 } 61 // 寻找主设备号在384~511的设备 62 for index in (DEV_MAJOR_DYN_EXT_END + 1..DEV_MAJOR_DYN_EXT_START + 1).rev() { 63 if let Some(chardevss) = chardevs.get(Self::major_to_index(index)) { 64 let mut flag = true; 65 for item in chardevss { 66 if item.device_number().major() == index { 67 flag = false; 68 break; 69 } 70 } 71 if flag { 72 // 如果数组中不存在主设备号等于index的设备 73 return Ok(index); // 返回可用的主设备号 74 } 75 } 76 } 77 return Err(SystemError::EBUSY); 78 } 79 80 /// @brief: 注册设备号,该函数需要指定主设备号 81 /// @parameter: from: 主设备号 82 /// count: 次设备号数量 83 /// name: 字符设备名 84 /// @return: 如果注册成功,返回设备号,否则,返回错误码 85 #[allow(dead_code)] 86 pub fn register_chardev_region( 87 from: DeviceNumber, 88 count: usize, 89 name: &'static str, 90 ) -> Result<DeviceNumber, SystemError> { 91 Self::__register_chardev_region(from, count, name) 92 } 93 94 /// @brief: 注册设备号,该函数自动分配主设备号 95 /// @parameter: baseminor: 次设备号 96 /// count: 次设备号数量 97 /// name: 字符设备名 98 /// @return: 如果注册成功,返回,否则,返回false 99 #[allow(dead_code)] 100 pub fn alloc_chardev_region( 101 baseminor: usize, 102 count: usize, 103 name: &'static str, 104 ) -> Result<DeviceNumber, SystemError> { 105 Self::__register_chardev_region(mkdev(0, baseminor), count, name) 106 } 107 108 /// @brief: 注册设备号 109 /// @parameter: device_number: 设备号,主设备号如果为0,则动态分配 110 /// minorct: 次设备号数量 111 /// name: 字符设备名 112 /// @return: 如果注册成功,返回设备号,否则,返回错误码 113 fn __register_chardev_region( 114 device_number: DeviceNumber, 115 minorct: usize, 116 name: &'static str, 117 ) -> Result<DeviceNumber, SystemError> { 118 let mut major = device_number.major(); 119 let baseminor = device_number.minor(); 120 if major >= DEV_MAJOR_MAX { 121 kerror!( 122 "DEV {} major requested {} is greater than the maximum {}\n", 123 name, 124 major, 125 DEV_MAJOR_MAX - 1 126 ); 127 } 128 if minorct > MINOR_MASK + 1 - baseminor { 129 kerror!("DEV {} minor range requested ({}-{}) is out of range of maximum range ({}-{}) for a single major\n", 130 name, baseminor, baseminor + minorct - 1, 0, MINOR_MASK); 131 } 132 let chardev = DeviceStruct::new(mkdev(major, baseminor), minorct, name); 133 if major == 0 { 134 // 如果主设备号为0,则自动分配主设备号 135 major = Self::find_dynamic_major().expect("Find synamic major error.\n"); 136 } 137 if let Some(items) = CHARDEVS.lock().get_mut(Self::major_to_index(major)) { 138 let mut insert_index: usize = 0; 139 for (index, item) in items.iter().enumerate() { 140 insert_index = index; 141 match item.device_number().major().cmp(&major) { 142 core::cmp::Ordering::Less => continue, 143 core::cmp::Ordering::Greater => { 144 break; // 大于则向后插入 145 } 146 core::cmp::Ordering::Equal => { 147 if item.device_number().minor() + item.minorct() <= baseminor { 148 continue; // 下一个主设备号大于或者次设备号大于被插入的次设备号最大值 149 } 150 if item.base_minor() >= baseminor + minorct { 151 break; // 在此处插入 152 } 153 return Err(SystemError::EBUSY); // 存在重合的次设备号 154 } 155 } 156 } 157 items.insert(insert_index, chardev); 158 } 159 return Ok(mkdev(major, baseminor)); 160 } 161 162 /// @brief: 注销设备号 163 /// @parameter: major: 主设备号,如果为0,动态分配 164 /// baseminor: 起始次设备号 165 /// minorct: 次设备号数量 166 /// @return: 如果注销成功,返回(),否则,返回错误码 167 fn __unregister_chardev_region( 168 device_number: DeviceNumber, 169 minorct: usize, 170 ) -> Result<(), SystemError> { 171 if let Some(items) = CHARDEVS 172 .lock() 173 .get_mut(Self::major_to_index(device_number.major())) 174 { 175 for (index, item) in items.iter().enumerate() { 176 if item.device_number() == device_number && item.minorct() == minorct { 177 // 设备号和数量都相等 178 items.remove(index); 179 return Ok(()); 180 } 181 } 182 } 183 return Err(SystemError::EBUSY); 184 } 185 186 /// @brief: 字符设备注册 187 /// @parameter: cdev: 字符设备实例 188 /// dev_t: 字符设备号 189 /// range: 次设备号范围 190 /// @return: none 191 #[allow(dead_code)] 192 pub fn cdev_add( 193 cdev: Arc<dyn CharDevice>, 194 id_table: IdTable, 195 range: usize, 196 ) -> Result<(), SystemError> { 197 if Into::<usize>::into(id_table.device_number()) == 0 { 198 kerror!("Device number can't be 0!\n"); 199 } 200 device_manager().add_device(cdev.clone())?; 201 kobj_map( 202 DEVMAP.clone(), 203 id_table.device_number(), 204 range, 205 cdev.clone(), 206 ); 207 208 return Ok(()); 209 } 210 211 /// @brief: 字符设备注销 212 /// @parameter: dev_t: 字符设备号 213 /// range: 次设备号范围 214 /// @return: none 215 #[allow(dead_code)] 216 pub fn cdev_del(id_table: IdTable, range: usize) { 217 device_manager().remove_device(&id_table); 218 kobj_unmap(DEVMAP.clone(), id_table.device_number(), range); 219 } 220 } 221