20 #include "modules/subsys/posix/VirtualTerminal.h" 21 #include "modules/subsys/posix/DevFs.h" 22 #include "modules/subsys/posix/PosixSubsystem.h" 23 #include "modules/system/console/Console.h" 24 #include "pedigree/kernel/process/Process.h" 26 extern DevFs *g_pDevFs;
28 VirtualTerminalManager::VirtualTerminalManager(
DevFsDirectory *parentDir)
29 : m_pTty(nullptr), m_CurrentTty(0), m_WantedTty(~0U), m_NumTtys(0),
30 m_ParentDir(parentDir), m_bSwitchingLocked(false), m_SystemMode(Text)
32 for (
size_t i = 0; i < MAX_VT; ++i)
34 m_Terminals[i].textio =
nullptr;
35 m_Terminals[i].file =
nullptr;
37 m_Terminals[i].owner =
nullptr;
40 ByteSet(&m_Terminals[i].mode, 0,
sizeof(m_Terminals[i].mode));
41 m_Terminals[i].mode.mode = VT_AUTO;
45 VirtualTerminalManager::~VirtualTerminalManager()
50 bool VirtualTerminalManager::initialise()
54 String(
"textui"), g_pDevFs->getNextInode(), g_pDevFs, m_ParentDir);
56 if (m_pTty->initialise(
false))
58 m_ParentDir->addEntry(m_pTty->getName(), m_pTty);
62 WARNING(
"POSIX: no /dev/tty - VirtualTerminalManager failed to " 64 g_pDevFs->revertInode();
74 m_ParentDir->addEntry(pTty1->
getName(), pTty1);
76 m_Terminals[0].textio = m_pTty;
77 m_Terminals[0].file = pTty1;
80 for (
size_t i = 1; i < 8; ++i)
83 ttyname.Format(
"tty%u", i + 1);
86 ttyname, g_pDevFs->getNextInode(), g_pDevFs, m_ParentDir);
91 m_ParentDir->addEntry(tio->
getName(), file);
93 m_Terminals[i].textio = tio;
94 m_Terminals[i].file = file;
104 WARNING(
"POSIX: failed to create " << ttyname);
105 g_pDevFs->revertInode();
117 ERROR(
"VirtualTerminalManager: trying to activate invalid VT #" << n);
120 else if (n == m_CurrentTty)
122 ERROR(
"VirtualTerminalManager: trying to activate current VT");
126 if (m_bSwitchingLocked)
128 ERROR(
"VirtualTerminalManager: switching is currently locked");
132 struct vt_mode currentMode = getTerminalMode(m_CurrentTty);
134 if (currentMode.mode == VT_AUTO)
136 NOTICE(
"VirtualTerminalManager: switching from auto VT");
139 m_Terminals[m_CurrentTty].textio->unmarkPrimary();
141 m_Terminals[m_CurrentTty].textio->markPrimary();
144 sendSignal(m_CurrentTty,
true);
148 NOTICE(
"VirtualTerminalManager: switching from owned VT");
153 sendSignal(m_CurrentTty,
false);
159 if (m_WantedTty == static_cast<size_t>(~0))
162 NOTICE(
"VirtualTerminalManager: can't acknowledge as no switch in " 167 if (perm == Disallowed)
170 NOTICE(
"VirtualTerminalManager: VT switch disallowed");
171 m_WantedTty =
static_cast<size_t>(~0U);
175 NOTICE(
"VirtualTerminalManager: VT switch allowed");
178 m_Terminals[m_CurrentTty].textio->unmarkPrimary();
179 m_CurrentTty = m_WantedTty;
180 m_Terminals[m_CurrentTty].textio->markPrimary();
183 sendSignal(m_CurrentTty,
true);
188 for (
size_t i = 0; i < MAX_VT; ++i)
190 if (m_Terminals[i].textio ==
nullptr)
192 NOTICE(
"VirtualTerminalManager: opening inactive VT #" << i);
195 ttyname.Format(
"tty%u", i + 1);
198 ttyname, g_pDevFs->getNextInode(), g_pDevFs, m_ParentDir);
203 m_ParentDir->addEntry(tio->
getName(), file);
205 m_Terminals[i].textio = tio;
206 m_Terminals[i].file = file;
218 WARNING(
"POSIX: failed to create " << ttyname);
219 g_pDevFs->revertInode();
230 m_bSwitchingLocked = locked;
233 size_t VirtualTerminalManager::getCurrentTerminalNumber()
const 238 TextIO *VirtualTerminalManager::getCurrentTerminal()
const 240 return m_Terminals[m_CurrentTty].textio;
243 File *VirtualTerminalManager::getCurrentTerminalFile()
const 245 return m_Terminals[m_CurrentTty].file;
251 NOTICE(
"getTerminalMode #" << n);
252 return m_Terminals[n].mode;
258 NOTICE(
"setTerminalMode #" << n);
259 m_Terminals[n].mode = mode;
262 if (mode.mode == VT_PROCESS)
264 m_Terminals[n].owner =
269 m_Terminals[n].owner =
nullptr;
274 struct vt_stat VirtualTerminalManager::getState() const
278 state.v_active = m_CurrentTty + 1;
281 for (
size_t i = 0; i < MAX_VT; ++i)
283 if (m_Terminals[i].textio !=
nullptr)
285 state.v_state |= (1 << (i + 1));
290 NOTICE(
" -> active = " << state.v_active);
291 NOTICE(
" -> state = " <<
Hex << state.v_state);
296 void VirtualTerminalManager::setSystemMode(SystemMode mode)
301 VirtualTerminalManager::SystemMode VirtualTerminalManager::getSystemMode()
const 306 void VirtualTerminalManager::setInputMode(
size_t n, TextIO::InputMode newMode)
308 if (!m_Terminals[n].textio)
311 "VirtualTerminalManager: can't set mode of VT #" 312 << n <<
" as it is inactive");
316 m_Terminals[n].textio->setMode(newMode);
319 TextIO::InputMode VirtualTerminalManager::getInputMode(
size_t n)
const 321 if (!m_Terminals[n].textio)
324 "VirtualTerminalManager: can't get mode of VT #" 325 << n <<
" as it is inactive");
326 return TextIO::Standard;
329 return m_Terminals[n].textio->getMode();
332 void VirtualTerminalManager::sendSignal(
size_t n,
bool acq)
334 if (!m_Terminals[n].textio)
337 "VirtualTerminalManager: can't send signal to VT #" 338 << n <<
" as it is inactive");
342 auto mode = getTerminalMode(n);
343 if (mode.mode != VT_PROCESS)
346 "VirtualTerminalManager: can't send signal to VT #" 347 << n <<
" as it is not owned");
352 Process *pProcess = m_Terminals[n].owner;
357 ERROR(
"VirtualTerminal::sendSignal: no subsystem");
361 NOTICE(
"VirtualTerminalManager: signaling VT #" << n);
363 pProcess->
getThread(0), acq ? mode.acqsig : mode.relsig);
void activate(size_t n)
Starts the process of activating the given tty.
void reportPermission(SwitchPermission perm)
void lockSwitching(bool locked)
void writeStr(const char *s, size_t len)
static ProcessorInformation & information()
bool initialise(bool bClear=true)
void setTerminalMode(size_t n, struct vt_mode mode)
Thread * getThread(size_t n)
virtual void sendSignal(Thread *pThread, int signal, bool yield=true)