ReactOS 0.4.16-dev-106-g10b08aa
kdterminal.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS KDBG Kernel Debugger Terminal Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: KD Terminal Management
5 * COPYRIGHT: Copyright 2005 Gregor Anich <blight@blight.eu.org>
6 * Copyright 2022-2023 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <ntoskrnl.h>
12#include "kd.h"
13#include "kdterminal.h"
14
15#define KdbpGetCharKeyboard(ScanCode) KdbpTryGetCharKeyboard((ScanCode), 0)
16CHAR
18
19#define KdbpGetCharSerial() KdbpTryGetCharSerial(0)
20CHAR
23
24VOID
27
28
29/* GLOBALS *******************************************************************/
30
31/* KD Controlling Terminal */
32ULONG KdbDebugState = 0; /* KDBG Settings (NOECHO, KDSERIAL) */
37
38static CHAR KdTermNextKey = ANSI_NULL; /* 1-character input queue buffer */
39
40
41/* FUNCTIONS *****************************************************************/
42
52{
53 /* Determine whether the controlling terminal is a serial terminal:
54 * serial output is enabled *and* KDSERIAL is set (i.e. user input
55 * through serial). */
57#if 0
58 // Old logic where KDSERIAL also enables serial output.
61#else
62 // New logic where KDSERIAL does not necessarily enable serial output.
65#endif
66
67 /* Flush the input buffer */
69
70 if (KdTermSerial)
71 {
73
74 /* Enable line-wrap */
75 KdbpSendCommandSerial("\x1b[?7h");
76
77 /*
78 * Query terminal type.
79 * Historically it was done with CTRL-E ('\x05'), however nowadays
80 * terminals respond to it with an empty (or a user-configurable)
81 * string. Instead, use the VT52-compatible 'ESC Z' sequence or the
82 * VT100-compatible 'ESC[c' one.
83 */
84 KdbpSendCommandSerial("\x1b[c");
86
87 Length = 0;
88 for (;;)
89 {
90 /* Verify we get an answer, but don't care about it */
91 if (KdbpTryGetCharSerial(5000) == -1)
92 break;
93 ++Length;
94 }
95
96 /* Terminal is connected (TRUE) or not connected (FALSE) */
97 KdTermConnected = (Length > 0);
98 }
99 else
100 {
101 /* Terminal is not serial, assume it's *not* connected */
103 }
104 return KdTermConnected;
105}
106
109 _Out_ PSIZE TermSize)
110{
111 static CHAR Buffer[128];
112 CHAR c;
113 LONG NumberOfCols = -1; // Or initialize to TermSize->cx ??
114 LONG NumberOfRows = -1; // Or initialize to TermSize->cy ??
115
116 /* Retrieve the size of the controlling terminal only when it is serial */
118 {
119 /* Flush the input buffer */
121
122 /* Try to query the terminal size. A reply looks like "\x1b[8;24;80t" */
124 KdbpSendCommandSerial("\x1b[18t");
126
127 c = KdbpTryGetCharSerial(5000);
128 if (c == KEY_ESC)
129 {
130 c = KdbpTryGetCharSerial(5000);
131 if (c == '[')
132 {
133 ULONG Length = 0;
134 for (;;)
135 {
136 c = KdbpTryGetCharSerial(5000);
137 if (c == -1)
138 break;
139
140 Buffer[Length++] = c;
141 if (isalpha(c) || Length >= (sizeof(Buffer) - 1))
142 break;
143 }
145
146 if (Buffer[0] == '8' && Buffer[1] == ';')
147 {
148 SIZE_T i;
149 for (i = 2; (i < Length) && (Buffer[i] != ';'); i++);
150
151 if (Buffer[i] == ';')
152 {
153 Buffer[i++] = ANSI_NULL;
154
155 /* Number of rows is now at Buffer + 2
156 * and number of columns at Buffer + i */
157 NumberOfRows = strtoul(Buffer + 2, NULL, 0);
158 NumberOfCols = strtoul(Buffer + i, NULL, 0);
160 }
161 }
162 }
163 /* Clear further characters */
164 while (KdbpTryGetCharSerial(5000) != -1);
165 }
166 }
167
168 if (NumberOfCols <= 0)
169 {
170 /* Set the number of columns to the default */
172 NumberOfCols = (SCREEN_WIDTH / 8 /*BOOTCHAR_WIDTH*/);
173 else
174 NumberOfCols = 80;
175 }
176 if (NumberOfRows <= 0)
177 {
178 /* Set the number of rows to the default */
180 NumberOfRows = (SCREEN_HEIGHT / (13 /*BOOTCHAR_HEIGHT*/ + 1));
181 else
182 NumberOfRows = 24;
183 }
184
185 TermSize->cx = NumberOfCols;
186 TermSize->cy = NumberOfRows;
187
188 // KdIoPrintf("Cols/Rows: %dx%d\n", TermSize->cx, TermSize->cy);
189
190 return KdTermReportsSize;
191}
192
196VOID
198{
201 {
202 while (KdbpTryGetCharSerial(1) != -1);
203 }
204 else
205 {
207 while (KdbpTryGetCharKeyboard(&ScanCode, 1) != -1);
208 }
209}
210
216CHAR
219{
220 CHAR Key;
221
222 *ScanCode = 0;
223
225 {
228 if (Key == KEY_ESC) /* ESC */
229 {
231 if (Key == '[')
232 {
234 switch (Key)
235 {
236 case 'A':
238 break;
239 case 'B':
241 break;
242 case 'C':
243 break;
244 case 'D':
245 break;
246 }
247 }
248 }
249 }
250 else
251 {
254 }
255
256 /* Check for return */
257 if (Key == '\r')
258 {
259 /*
260 * We might need to discard the next '\n' which most clients
261 * should send after \r. Wait a bit to make sure we receive it.
262 */
264
267 else
269
270 if (KdTermNextKey == '\n' || KdTermNextKey == -1) /* \n or no response at all */
272 }
273
274 return Key;
275}
276
277/* EOF */
unsigned char BOOLEAN
UINT ScanCode
Definition: VirtualKey.c:24
#define isalpha(c)
Definition: acclib.h:74
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
Definition: bufpool.h:45
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
const GLubyte * c
Definition: glext.h:8905
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
KDP_DEBUG_MODE KdpDebugMode
Definition: kdio.c:46
VOID KdpFlushTerminalInput(VOID)
Flushes terminal input (either serial or PS/2).
Definition: kdterminal.c:197
BOOLEAN KdTermConnected
Definition: kdterminal.c:34
VOID KdbpSendCommandSerial(_In_ PCSTR Command)
Definition: kdserial.c:17
CHAR KdbpTryGetCharKeyboard(PULONG ScanCode, ULONG Retry)
Definition: kdps2kbd.c:104
static CHAR KdTermNextKey
Definition: kdterminal.c:38
#define KdbpGetCharSerial()
Definition: kdterminal.c:19
BOOLEAN KdpUpdateTerminalSize(_Out_ PSIZE TermSize)
Definition: kdterminal.c:108
ULONG KdbDebugState
Definition: kdterminal.c:32
#define KdbpGetCharKeyboard(ScanCode)
Definition: kdterminal.c:15
CHAR KdbpTryGetCharSerial(_In_ ULONG Retry)
Definition: kdserial.c:25
SIZE KdTermSize
Definition: kdterminal.c:33
BOOLEAN KdTermReportsSize
Definition: kdterminal.c:36
BOOLEAN KdpInitTerminal(VOID)
Initializes the controlling terminal.
Definition: kdterminal.c:51
BOOLEAN KdTermSerial
Definition: kdterminal.c:35
CHAR KdpReadTermKey(_Out_ PULONG ScanCode)
Reads one character from the terminal. This function returns a scan code even when reading is done fr...
Definition: kdterminal.c:217
@ KD_DEBUG_KDSERIAL
Definition: kdterminal.h:36
#define KEY_SCAN_DOWN
Definition: kdterminal.h:15
#define KEY_SCAN_UP
Definition: kdterminal.h:14
#define c
Definition: ke_i.h:80
#define KEY_ESC
Definition: keycodes.h:49
#define KeStallExecutionProcessor(MicroSeconds)
Definition: precomp.h:27
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define ANSI_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define SCREEN_WIDTH
Definition: pc98video.c:27
#define SCREEN_HEIGHT
Definition: pc98video.c:28
long LONG
Definition: pedump.c:60
Definition: shell.h:41
UCHAR Screen
Definition: kd.h:100
UCHAR Serial
Definition: kd.h:101
uint32_t * PULONG
Definition: typedefs.h:59
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG
Definition: typedefs.h:59
char CHAR
Definition: xmlstorage.h:175