123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621 |
- use alloc::{
- string::{String, ToString},
- sync::{Arc, Weak},
- };
- use system_error::SystemError;
- use unified_init::macros::unified_init;
- use crate::{
- arch::ipc::signal::Signal,
- driver::{
- base::{
- char::CharDevice,
- class::Class,
- device::{
- bus::Bus,
- device_number::{DeviceNumber, Major},
- device_register,
- driver::Driver,
- Device, DeviceKObjType, DeviceType, IdTable,
- },
- kobject::{KObject, LockedKObjectState},
- kset::KSet,
- },
- serial::serial_init,
- },
- filesystem::{
- devfs::{devfs_register, DevFS, DeviceINode},
- kernfs::KernFSInode,
- vfs::{file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata},
- },
- init::initcall::INITCALL_DEVICE,
- libs::{
- rwlock::{RwLock, RwLockWriteGuard},
- spinlock::SpinLockGuard,
- },
- mm::VirtAddr,
- net::event_poll::{EPollItem, EventPoll},
- process::ProcessManager,
- syscall::user_access::{UserBufferReader, UserBufferWriter},
- };
- use super::{
- kthread::tty_flush_thread_init,
- pty::unix98pty::ptmx_open,
- sysfs::sys_class_tty_instance,
- termios::WindowSize,
- tty_core::{TtyCore, TtyFlag, TtyIoctlCmd},
- tty_driver::{TtyDriver, TtyDriverManager, TtyDriverSubType, TtyDriverType, TtyOperation},
- tty_job_control::TtyJobCtrlManager,
- virtual_terminal::vty_init,
- };
- #[derive(Debug)]
- pub struct InnerTtyDevice {
- /// 当前设备所述的kset
- kset: Option<Arc<KSet>>,
- parent_kobj: Option<Weak<dyn KObject>>,
- /// 当前设备所述的总线
- bus: Option<Weak<dyn Bus>>,
- inode: Option<Arc<KernFSInode>>,
- driver: Option<Weak<dyn Driver>>,
- can_match: bool,
- metadata: Metadata,
- }
- impl InnerTtyDevice {
- pub fn new() -> Self {
- Self {
- kset: None,
- parent_kobj: None,
- bus: None,
- inode: None,
- driver: None,
- can_match: false,
- metadata: Metadata::new(FileType::CharDevice, ModeType::from_bits_truncate(0o755)),
- }
- }
- pub fn metadata_mut(&mut self) -> &mut Metadata {
- &mut self.metadata
- }
- }
- #[derive(Debug, PartialEq)]
- pub enum TtyType {
- Tty,
- Pty(PtyType),
- }
- #[derive(Debug, PartialEq)]
- pub enum PtyType {
- Ptm,
- Pts,
- }
- #[derive(Debug)]
- #[cast_to([sync] Device)]
- pub struct TtyDevice {
- name: String,
- id_table: IdTable,
- tty_type: TtyType,
- inner: RwLock<InnerTtyDevice>,
- kobj_state: LockedKObjectState,
- /// TTY所属的文件系统
- fs: RwLock<Weak<DevFS>>,
- }
- impl TtyDevice {
- pub fn new(name: String, id_table: IdTable, tty_type: TtyType) -> Arc<TtyDevice> {
- let dev_num = id_table.device_number();
- let dev = TtyDevice {
- name,
- id_table,
- inner: RwLock::new(InnerTtyDevice::new()),
- kobj_state: LockedKObjectState::new(None),
- fs: RwLock::new(Weak::default()),
- tty_type,
- };
- dev.inner.write().metadata.raw_dev = dev_num;
- Arc::new(dev)
- }
- pub fn inner_write(&self) -> RwLockWriteGuard<InnerTtyDevice> {
- self.inner.write()
- }
- }
- impl IndexNode for TtyDevice {
- fn open(
- &self,
- mut data: SpinLockGuard<FilePrivateData>,
- mode: &crate::filesystem::vfs::file::FileMode,
- ) -> Result<(), SystemError> {
- if let FilePrivateData::Tty(_) = &*data {
- return Ok(());
- }
- if self.tty_type == TtyType::Pty(PtyType::Ptm) {
- return ptmx_open(data, mode);
- }
- let dev_num = self.metadata()?.raw_dev;
- let (index, driver) =
- TtyDriverManager::lookup_tty_driver(dev_num).ok_or(SystemError::ENODEV)?;
- let tty = TtyDriver::open_tty(index, driver)?;
- // 设置privdata
- *data = FilePrivateData::Tty(TtyFilePrivateData {
- tty: tty.clone(),
- mode: *mode,
- });
- let ret = tty.open(tty.core());
- if let Err(err) = ret {
- if err == SystemError::ENOSYS {
- return Err(SystemError::ENODEV);
- }
- return Err(err);
- }
- let driver = tty.core().driver();
- // 考虑noctty(当前tty)
- if !(mode.contains(FileMode::O_NOCTTY) && dev_num == DeviceNumber::new(Major::TTY_MAJOR, 0)
- || dev_num == DeviceNumber::new(Major::TTYAUX_MAJOR, 1)
- || (driver.tty_driver_type() == TtyDriverType::Pty
- && driver.tty_driver_sub_type() == TtyDriverSubType::PtyMaster))
- {
- let pcb = ProcessManager::current_pcb();
- let pcb_tty = pcb.sig_info_irqsave().tty();
- if pcb_tty.is_none() && tty.core().contorl_info_irqsave().session.is_none() {
- TtyJobCtrlManager::proc_set_tty(tty);
- }
- }
- Ok(())
- }
- fn read_at(
- &self,
- _offset: usize,
- len: usize,
- buf: &mut [u8],
- data: SpinLockGuard<FilePrivateData>,
- ) -> Result<usize, system_error::SystemError> {
- let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = &*data {
- (tty_priv.tty(), tty_priv.mode)
- } else {
- return Err(SystemError::EIO);
- };
- drop(data);
- let ld = tty.ldisc();
- let mut offset = 0;
- let mut cookie = false;
- loop {
- let mut size = if len > buf.len() { buf.len() } else { len };
- size = ld.read(tty.clone(), buf, size, &mut cookie, offset, mode)?;
- // 没有更多数据
- if size == 0 {
- break;
- }
- offset += size;
- // 缓冲区写满
- if offset >= len {
- break;
- }
- // 没有更多数据
- if !cookie {
- break;
- }
- }
- return Ok(offset);
- }
- fn write_at(
- &self,
- _offset: usize,
- len: usize,
- buf: &[u8],
- data: SpinLockGuard<FilePrivateData>,
- ) -> Result<usize, system_error::SystemError> {
- let mut count = len;
- let (tty, mode) = if let FilePrivateData::Tty(tty_priv) = &*data {
- (tty_priv.tty(), tty_priv.mode)
- } else {
- return Err(SystemError::EIO);
- };
- drop(data);
- let ld = tty.ldisc();
- let core = tty.core();
- let mut chunk = 2048;
- if core.flags().contains(TtyFlag::NO_WRITE_SPLIT) {
- chunk = 65536;
- }
- chunk = chunk.min(count);
- let pcb = ProcessManager::current_pcb();
- let mut written = 0;
- loop {
- // 至少需要写多少
- let size = chunk.min(count);
- // 将数据从buf拷贝到writebuf
- let ret = ld.write(tty.clone(), &buf[written..], size, mode)?;
- written += ret;
- count -= ret;
- if count == 0 {
- break;
- }
- if pcb.sig_info_irqsave().sig_pending().has_pending() {
- return Err(SystemError::ERESTARTSYS);
- }
- }
- if written > 0 {
- // todo: 更新时间
- }
- Ok(written)
- }
- fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
- todo!()
- }
- fn as_any_ref(&self) -> &dyn core::any::Any {
- self
- }
- fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
- todo!()
- }
- fn metadata(&self) -> Result<crate::filesystem::vfs::Metadata, SystemError> {
- Ok(self.inner.read().metadata.clone())
- }
- fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
- let mut guard = self.inner_write();
- guard.metadata = metadata.clone();
- Ok(())
- }
- fn close(&self, data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
- let (tty, _mode) = if let FilePrivateData::Tty(tty_priv) = &*data {
- (tty_priv.tty(), tty_priv.mode)
- } else {
- return Err(SystemError::EIO);
- };
- drop(data);
- tty.close(tty.clone())
- }
- fn resize(&self, _len: usize) -> Result<(), SystemError> {
- Ok(())
- }
- fn ioctl(&self, cmd: u32, arg: usize, data: &FilePrivateData) -> Result<usize, SystemError> {
- let (tty, _) = if let FilePrivateData::Tty(tty_priv) = data {
- (tty_priv.tty(), tty_priv.mode)
- } else {
- return Err(SystemError::EIO);
- };
- match cmd {
- TtyIoctlCmd::TIOCSETD
- | TtyIoctlCmd::TIOCSBRK
- | TtyIoctlCmd::TIOCCBRK
- | TtyIoctlCmd::TCSBRK
- | TtyIoctlCmd::TCSBRKP => {
- TtyJobCtrlManager::tty_check_change(tty.clone(), Signal::SIGTTOU)?;
- if cmd != TtyIoctlCmd::TIOCCBRK {
- todo!()
- }
- }
- EventPoll::ADD_EPOLLITEM => {
- let _ = UserBufferReader::new(
- arg as *const Arc<EPollItem>,
- core::mem::size_of::<Arc<EPollItem>>(),
- false,
- )?;
- let epitem = unsafe { &*(arg as *const Arc<EPollItem>) };
- let core = tty.core();
- core.add_epitem(epitem.clone());
- return Ok(0);
- }
- _ => {}
- }
- match cmd {
- TtyIoctlCmd::TIOCGWINSZ => {
- let core = tty.core();
- let winsize = *core.window_size();
- let mut user_writer = UserBufferWriter::new(
- VirtAddr::new(arg).as_ptr::<WindowSize>(),
- core::mem::size_of::<WindowSize>(),
- true,
- )?;
- let err = user_writer.copy_one_to_user(&winsize, 0);
- if err.is_err() {
- return Err(SystemError::EFAULT);
- }
- return Ok(0);
- }
- TtyIoctlCmd::TIOCSWINSZ => {
- let reader = UserBufferReader::new(
- arg as *const (),
- core::mem::size_of::<WindowSize>(),
- true,
- )?;
- let user_winsize = reader.read_one_from_user::<WindowSize>(0)?;
- let ret = tty.resize(tty.clone(), *user_winsize);
- if ret != Err(SystemError::ENOSYS) {
- return ret.map(|_| 0);
- } else {
- return tty.tty_do_resize(*user_winsize).map(|_| 0);
- }
- }
- _ => match TtyJobCtrlManager::job_ctrl_ioctl(tty.clone(), cmd, arg) {
- Ok(_) => {
- return Ok(0);
- }
- Err(e) => {
- if e != SystemError::ENOIOCTLCMD {
- return Err(e);
- }
- }
- },
- }
- match tty.ioctl(tty.clone(), cmd, arg) {
- Ok(_) => {
- return Ok(0);
- }
- Err(e) => {
- if e != SystemError::ENOIOCTLCMD {
- return Err(e);
- }
- }
- }
- tty.ldisc().ioctl(tty, cmd, arg)?;
- Ok(0)
- }
- fn poll(&self, private_data: &FilePrivateData) -> Result<usize, SystemError> {
- let (tty, _) = if let FilePrivateData::Tty(tty_priv) = private_data {
- (tty_priv.tty.clone(), tty_priv.mode)
- } else {
- return Err(SystemError::EIO);
- };
- tty.ldisc().poll(tty)
- }
- }
- impl DeviceINode for TtyDevice {
- fn set_fs(&self, fs: alloc::sync::Weak<crate::filesystem::devfs::DevFS>) {
- *self.fs.write() = fs;
- }
- }
- impl KObject for TtyDevice {
- fn as_any_ref(&self) -> &dyn core::any::Any {
- self
- }
- fn set_inode(&self, inode: Option<Arc<crate::filesystem::kernfs::KernFSInode>>) {
- self.inner.write().inode = inode;
- }
- fn inode(&self) -> Option<Arc<crate::filesystem::kernfs::KernFSInode>> {
- self.inner.read().inode.clone()
- }
- fn parent(&self) -> Option<alloc::sync::Weak<dyn KObject>> {
- self.inner.read().parent_kobj.clone()
- }
- fn set_parent(&self, parent: Option<alloc::sync::Weak<dyn KObject>>) {
- self.inner.write().parent_kobj = parent
- }
- fn kset(&self) -> Option<Arc<crate::driver::base::kset::KSet>> {
- self.inner.read().kset.clone()
- }
- fn set_kset(&self, kset: Option<Arc<crate::driver::base::kset::KSet>>) {
- self.inner.write().kset = kset
- }
- fn kobj_type(&self) -> Option<&'static dyn crate::driver::base::kobject::KObjType> {
- Some(&DeviceKObjType)
- }
- fn set_kobj_type(&self, _ktype: Option<&'static dyn crate::driver::base::kobject::KObjType>) {}
- fn name(&self) -> alloc::string::String {
- self.name.to_string()
- }
- fn set_name(&self, _name: alloc::string::String) {
- // self.name = name
- }
- fn kobj_state(
- &self,
- ) -> crate::libs::rwlock::RwLockReadGuard<crate::driver::base::kobject::KObjectState> {
- self.kobj_state.read()
- }
- fn kobj_state_mut(
- &self,
- ) -> crate::libs::rwlock::RwLockWriteGuard<crate::driver::base::kobject::KObjectState> {
- self.kobj_state.write()
- }
- fn set_kobj_state(&self, state: crate::driver::base::kobject::KObjectState) {
- *self.kobj_state.write() = state
- }
- }
- impl Device for TtyDevice {
- fn dev_type(&self) -> crate::driver::base::device::DeviceType {
- DeviceType::Char
- }
- fn id_table(&self) -> crate::driver::base::device::IdTable {
- self.id_table.clone()
- }
- fn bus(&self) -> Option<Weak<dyn Bus>> {
- self.inner.read().bus.clone()
- }
- fn set_bus(&self, bus: Option<alloc::sync::Weak<dyn crate::driver::base::device::bus::Bus>>) {
- self.inner.write().bus = bus
- }
- fn set_class(&self, _class: Option<Weak<dyn crate::driver::base::class::Class>>) {
- // do nothing
- }
- fn class(&self) -> Option<Arc<dyn Class>> {
- sys_class_tty_instance()
- .cloned()
- .map(|x| x as Arc<dyn Class>)
- }
- fn driver(&self) -> Option<Arc<dyn crate::driver::base::device::driver::Driver>> {
- self.inner.read().driver.clone()?.upgrade()
- }
- fn set_driver(
- &self,
- driver: Option<alloc::sync::Weak<dyn crate::driver::base::device::driver::Driver>>,
- ) {
- self.inner.write().driver = driver
- }
- fn is_dead(&self) -> bool {
- false
- }
- fn can_match(&self) -> bool {
- self.inner.read().can_match
- }
- fn set_can_match(&self, can_match: bool) {
- self.inner.write().can_match = can_match
- }
- fn state_synced(&self) -> bool {
- true
- }
- }
- impl CharDevice for TtyDevice {
- fn read(&self, _len: usize, _buf: &mut [u8]) -> Result<usize, SystemError> {
- todo!()
- }
- fn write(&self, _len: usize, _buf: &[u8]) -> Result<usize, SystemError> {
- todo!()
- }
- fn sync(&self) -> Result<(), SystemError> {
- todo!()
- }
- }
- #[derive(Debug, Clone)]
- pub struct TtyFilePrivateData {
- pub tty: Arc<TtyCore>,
- pub mode: FileMode,
- }
- impl TtyFilePrivateData {
- pub fn tty(&self) -> Arc<TtyCore> {
- self.tty.clone()
- }
- }
- /// 初始化tty设备和console子设备
- #[unified_init(INITCALL_DEVICE)]
- #[inline(never)]
- pub fn tty_init() -> Result<(), SystemError> {
- let tty = TtyDevice::new(
- "tty0".to_string(),
- IdTable::new(
- String::from("tty0"),
- Some(DeviceNumber::new(Major::TTY_MAJOR, 0)),
- ),
- TtyType::Tty,
- );
- let console = TtyDevice::new(
- "console".to_string(),
- IdTable::new(
- String::from("console"),
- Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
- ),
- TtyType::Tty,
- );
- // 注册tty设备
- // CharDevOps::cdev_add(
- // tty.clone() as Arc<dyn CharDevice>,
- // IdTable::new(
- // String::from("tty0"),
- // Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 0)),
- // ),
- // 1,
- // )?;
- // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 0), 1, "/dev/tty")?;
- // 注册console设备
- // CharDevOps::cdev_add(
- // console.clone() as Arc<dyn CharDevice>,
- // IdTable::new(
- // String::from("console"),
- // Some(DeviceNumber::new(Major::TTYAUX_MAJOR, 1)),
- // ),
- // 1,
- // )?;
- // CharDevOps::register_chardev_region(DeviceNumber::new(Major::TTYAUX_MAJOR, 1), 1, "/dev/tty")?;
- // 将这两个设备注册到devfs,TODO:这里console设备应该与tty在一个设备group里面
- device_register(tty.clone())?;
- device_register(console.clone())?;
- devfs_register(&tty.name.clone(), tty)?;
- devfs_register(&console.name.clone(), console)?;
- serial_init()?;
- tty_flush_thread_init();
- return vty_init();
- }
|