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