Author: ion Date: Sun Aug 18 17:47:19 2013 New Revision: 59772 URL: http://svn.reactos.org/svn/reactos?rev=59772&view=rev Log: [CPORTLIB/KDBG/FREELDR]: Fix CpGetByte and its callers -- it takes a 4th parameter for polling. [NTOSKRNL]: Implement InbvPortPollOnly and InbvPortGetByte. [NTOSKRNL]: Implement HeadlessCmdClearDisplay and HeadlessCmdGetByte. [SACDRV]: Implement the TimerDpcRoutine which calls HeadlessCmdGetByte. We now consume characters in the EMS port. [SACDRV]: Implement ConMgrSerialPortConsumer. We now do full VT-100 input parsing. DEL, BS, TAB, SPACE all work. Pressing ENTER results in an ASSERT in ConMgrProcessLine as expected.
Modified: trunk/reactos/boot/freeldr/freeldr/comm/rs232.c trunk/reactos/boot/freeldr/freeldr/windows/headless.c trunk/reactos/drivers/sac/driver/conmgr.c trunk/reactos/drivers/sac/driver/data.c trunk/reactos/drivers/sac/driver/dispatch.c trunk/reactos/drivers/sac/driver/sacdrv.h trunk/reactos/drivers/sac/driver/util.c trunk/reactos/include/reactos/libs/cportlib/cportlib.h trunk/reactos/lib/cportlib/cport.c trunk/reactos/ntoskrnl/ex/hdlsterm.c trunk/reactos/ntoskrnl/inbv/inbvport.c trunk/reactos/ntoskrnl/include/internal/hdl.h trunk/reactos/ntoskrnl/include/internal/inbv.h trunk/reactos/ntoskrnl/kd/i386/kdbg.c Modified: trunk/reactos/boot/freeldr/freeldr/comm/rs232.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/comm/rs232.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/boot/freeldr/freeldr/comm/rs232.c [iso-8859-1] (original) +++ trunk/reactos/boot/freeldr/freeldr/comm/rs232.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -100,7 +100,7 @@ if (PortInitialized == FALSE) return FALSE; - return (CpGetByte(&Rs232ComPort, ByteReceived, TRUE) == CP_GET_SUCCESS); + return (CpGetByte(&Rs232ComPort, ByteReceived, TRUE, FALSE) == CP_GET_SUCCESS); } /* Modified: trunk/reactos/boot/freeldr/freeldr/windows/headless.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windows/headless.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/boot/freeldr/freeldr/windows/headless.c [iso-8859-1] (original) +++ trunk/reactos/boot/freeldr/freeldr/windows/headless.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -143,7 +143,7 @@ WinLdrPortGetByte(IN ULONG PortId, OUT PUCHAR Data) { - return CpGetByte(&Port[PortId], Data, TRUE) == CP_GET_SUCCESS; + return CpGetByte(&Port[PortId], Data, TRUE, FALSE) == CP_GET_SUCCESS; } BOOLEAN @@ -151,7 +151,7 @@ { UCHAR Dummy; - return CpGetByte(&Port[PortId], &Dummy, FALSE) == CP_GET_SUCCESS; + return CpGetByte(&Port[PortId], &Dummy, FALSE, TRUE) == CP_GET_SUCCESS; } VOID Modified: trunk/reactos/drivers/sac/driver/conmgr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/conmgr.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/drivers/sac/driver/conmgr.c [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/conmgr.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -27,76 +27,10 @@ ULONG ExecutePostConsumerCommand; PSAC_CHANNEL ExecutePostConsumerCommandData; +BOOLEAN InputInEscape, InputInEscTab, ConMgrLastCharWasCR; +CHAR InputBuffer[80]; + /* FUNCTIONS *****************************************************************/ - -VOID -NTAPI -ConMgrSerialPortConsumer(VOID) -{ - NTSTATUS Status; - CHAR Char; - SAC_DBG(0x2000, "SAC TimerDpcRoutine: Entering.\n"); //bug - - /* Acquire the manager lock and make sure a channel is selected */ - SacAcquireMutexLock(); - ASSERT(CurrentChannel); - - /* Read whatever came off the serial port */ - for (Status = SerialBufferGetChar(&Char); - NT_SUCCESS(Status); - Status = SerialBufferGetChar(&Char)) - { - /* If nothing came through, bail out */ - if (Status == STATUS_NO_DATA_DETECTED) break; - } - - /* We're done, release the lock */ - SacReleaseMutexLock(); - SAC_DBG(0x2000, "SAC TimerDpcRoutine: Exiting.\n"); //bug -} - -VOID -NTAPI -ConMgrWorkerProcessEvents(IN PSAC_DEVICE_EXTENSION DeviceExtension) -{ - SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC WorkerProcessEvents: Entering.\n"); - - /* Enter the main loop */ - while (TRUE) - { - /* Wait for something to do */ - KeWaitForSingleObject(&DeviceExtension->Event, - Executive, - KernelMode, - FALSE, - NULL); - - /* Consume data off the serial port */ - ConMgrSerialPortConsumer(); - switch (ExecutePostConsumerCommand) - { - case 1: - /* A reboot was sent, do it */ - DoRebootCommand(FALSE); - break; - - case 2: - /* A close was sent, do it */ - ChanMgrCloseChannel(ExecutePostConsumerCommandData); - ChanMgrReleaseChannel(ExecutePostConsumerCommandData); - break; - - case 3: - /* A shutdown was sent, do it */ - DoRebootCommand(TRUE); - break; - } - - /* Clear the serial port consumer state */ - ExecutePostConsumerCommand = 0; - ExecutePostConsumerCommandData = NULL; - } -} VOID NTAPI @@ -512,6 +446,319 @@ return Status; } +VOID +NTAPI +ConMgrProcessInputLine(VOID) +{ + ASSERT(FALSE); +} + +#define Nothing 0 + +VOID +NTAPI +ConMgrSerialPortConsumer(VOID) +{ + NTSTATUS Status; + CHAR Char, LastChar; + CHAR WriteBuffer[2], ReadBuffer[2]; + ULONG ReadBufferSize, i; + WCHAR StringBuffer[2]; + SAC_DBG(SAC_DBG_MACHINE, "SAC TimerDpcRoutine: Entering.\n"); //bug + + /* Acquire the manager lock and make sure a channel is selected */ + SacAcquireMutexLock(); + ASSERT(CurrentChannel); + + /* Read whatever came off the serial port */ + for (Status = SerialBufferGetChar(&Char); + NT_SUCCESS(Status); + Status = SerialBufferGetChar(&Char)) + { + /* If nothing came through, bail out */ + if (Status == STATUS_NO_DATA_DETECTED) break; + + /* Check if ESC was pressed */ + if (Char == '\x1B') + { + /* Was it already pressed? */ + if (!InputInEscape) + { + /* First time ESC is pressed! Remember and reset TAB state */ + InputInEscTab = FALSE; + InputInEscape = TRUE; + continue; + } + } + else if (Char == '\t') + { + /* TAB was pressed, is it following ESC (VT-100 sequence)? */ + if (InputInEscape) + { + /* Yes! This must be the only ESC-TAB we see in once moment */ + ASSERT(InputInEscTab == FALSE); + + /* No longer treat us as being in ESC */ + InputInEscape = FALSE; + + /* ESC-TAB is the sequence for changing channels */ + Status = ConMgrAdvanceCurrentChannel(); + if (!NT_SUCCESS(Status)) break; + + /* Remember ESC-TAB was pressed */ + InputInEscTab = TRUE; + continue; + } + } + else if ((Char == '0') && (InputInEscTab)) + { + /* It this ESC-TAB-0? */ + ASSERT(InputInEscape == FALSE); + InputInEscTab = FALSE; + + /* If writes are already enabled, don't do this */ + if (!CurrentChannel->WriteEnabled) + { + /* Reset the channel, this is our special sequence */ + Status = ConMgrResetCurrentChannel(FALSE); + if (!NT_SUCCESS(Status)) break; + } + + continue; + } + else + { + /* This is ESC-TAB-something else */ + InputInEscTab = FALSE; + + /* If writes are already enabled, don't do this */ + if (!CurrentChannel->WriteEnabled) + { + /* Display the current channel */ + InputInEscape = FALSE; + Status = ConMgrDisplayCurrentChannel(); + if (!NT_SUCCESS(Status)) break; + continue; + } + } + + /* Check if an ESC-sequence was being typed into a command channel */ + if ((InputInEscape) && (CurrentChannel != SacChannel)) + { + /* Store the ESC in the current channel buffer */ + WriteBuffer[0] = '\x1B'; + ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR)); + } + + /* Check if we are no longer pressing ESC and exit the mode if so */ + if (Char != '\x1B') InputInEscape = FALSE; + + /* Whatever was typed in, save it int eh current channel */ + ChannelIWrite(CurrentChannel, &Char, sizeof(Char)); + + /* If this is a command channel, we're done, nothing to process */ + if (CurrentChannel != SacChannel) continue; + + /* Check for line feed right after a carriage return */ + if ((ConMgrLastCharWasCR) && (Char == '\n')) + { + /* Ignore the line feed, but clear the carriage return */ + ChannelIReadLast(CurrentChannel); + ConMgrLastCharWasCR = 0; + continue; + } + + /* Check if the user did a carriage return */ + ConMgrLastCharWasCR = (Char == '\n'); + + /* If the user did an "ENTER", we need to run the command */ + if ((Char == '\n') || (Char == '\r')) + { + /* Echo back to the terminal */ + SacPutString(L"\r\n"); + +DoLineParsing: + /* Inhibit the character (either CR or LF) */ + ChannelIReadLast(CurrentChannel); + + /* NULL-terminate the channel's input buffer */ + WriteBuffer[0] = ANSI_NULL; + ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR)); + + /* Loop over every last character */ + do + { + /* Read every character in the channel, and strip whitespace */ + LastChar = ChannelIReadLast(CurrentChannel); + WriteBuffer[0] = LastChar; + } while ((!(LastChar) || + (LastChar == ' ') || + (LastChar == '\t')) && + (ChannelIBufferLength(CurrentChannel))); + + /* Write back into the channel the last character */ + ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR)); + + /* NULL-terminate the input buffer */ + WriteBuffer[0] = ANSI_NULL; + ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(WCHAR)); + + /* Now loop over every first character */ + do + { + /* Read every character in the channel, and strip whitespace */ + ChannelIRead(CurrentChannel, + ReadBuffer, + sizeof(ReadBuffer), + &ReadBufferSize); + WriteBuffer[0] = ReadBuffer[0]; + } while ((ReadBufferSize) && + ((ReadBuffer[0] != ' ') || (ReadBuffer[0] != '\t'))); + + /* We read one more than we should, so treat that as our first one */ + InputBuffer[0] = ReadBuffer[0]; + i = 1; + + /* And now loop reading all the others */ + do + { + /* Read each character -- there should be max 80 */ + ChannelIRead(CurrentChannel, + ReadBuffer, + sizeof(ReadBuffer), + &ReadBufferSize); + ASSERT(i < SAC_VTUTF8_COL_WIDTH); + InputBuffer[i++] = ReadBuffer[0]; + } while (ReadBufferSize); + + /* Now go over the entire input stream */ + for (i = 0; InputBuffer[i]; i++) + { + /* Again it should be less than 80 characters */ + ASSERT(i < SAC_VTUTF8_COL_WIDTH); + + /* And upcase each character */ + Char = InputBuffer[i]; + if ((Char >= 'A') && (Char <= 'Z')) InputBuffer[i] = Char + ' '; + } + + /* Ok, at this point, no pending command should exist */ + ASSERT(ExecutePostConsumerCommand == Nothing); + + /* Go and process the input, then show the prompt again */ + ConMgrProcessInputLine(); + SacPutSimpleMessage(SAC_PROMPT); + + /* If the user typed a valid command, get out of here */ + if (ExecutePostConsumerCommand != Nothing) break; + + /* Keep going */ + continue; + } + + /* Check if the user typed backspace or delete */ + if ((Char == '\b') || (Char == '\x7F')) + { + /* Omit the last character, which should be the DEL/BS itself */ + if (ChannelIBufferLength(CurrentChannel)) + { + ChannelIReadLast(CurrentChannel); + } + + /* Omit the before-last character, which is the one to delete */ + if (ChannelIBufferLength(CurrentChannel)) + { + /* Also send two backspaces back to the console */ + SacPutString(L"\b \b"); + ChannelIReadLast(CurrentChannel); + } + + /* Keep going */ + continue; + } + + /* If the user pressed CTRL-C at this point, treat it like ENTER */ + if (Char == '\x03') goto DoLineParsing; + + /* Check if the user pressed TAB */ + if (Char == '\t') + { + /* Omit it, send a BELL, and keep going. We ignore TABs */ + ChannelIReadLast(CurrentChannel); + SacPutString(L"\a"); + continue; + } + + /* Check if the user is getting close to the end of the screen */ + if (ChannelIBufferLength(CurrentChannel) == (SAC_VTUTF8_COL_WIDTH - 2)) + { + /* Delete the last character, replacing it with this one instead */ + swprintf(StringBuffer, L"\b%c", Char); + SacPutString(StringBuffer); + + /* Omit the last two characters from the buffer */ + ChannelIReadLast(CurrentChannel); + ChannelIReadLast(CurrentChannel); + + /* NULL-terminate it */ + WriteBuffer[0] = Char; + ChannelIWrite(CurrentChannel, WriteBuffer, sizeof(CHAR)); + continue; + } + + /* Nothing of interest happened, just write the character back */ + swprintf(StringBuffer, L"%c", Char); + SacPutString(StringBuffer); + } + + /* We're done, release the lock */ + SacReleaseMutexLock(); + SAC_DBG(SAC_DBG_MACHINE, "SAC TimerDpcRoutine: Exiting.\n"); //bug +} + +VOID +NTAPI +ConMgrWorkerProcessEvents(IN PSAC_DEVICE_EXTENSION DeviceExtension) +{ + SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC WorkerProcessEvents: Entering.\n"); + + /* Enter the main loop */ + while (TRUE) + { + /* Wait for something to do */ + KeWaitForSingleObject(&DeviceExtension->Event, + Executive, + KernelMode, + FALSE, + NULL); + + /* Consume data off the serial port */ + ConMgrSerialPortConsumer(); + switch (ExecutePostConsumerCommand) + { + case 1: + /* A reboot was sent, do it */ + DoRebootCommand(FALSE); + break; + + case 2: + /* A close was sent, do it */ + ChanMgrCloseChannel(ExecutePostConsumerCommandData); + ChanMgrReleaseChannel(ExecutePostConsumerCommandData); + break; + + case 3: + /* A shutdown was sent, do it */ + DoRebootCommand(TRUE); + break; + } + + /* Clear the serial port consumer state */ + ExecutePostConsumerCommand = 0; + ExecutePostConsumerCommandData = NULL; + } +} + NTSTATUS NTAPI ConMgrGetChannelCloseMessage(IN PSAC_CHANNEL Channel, @@ -522,13 +769,6 @@ return STATUS_NOT_IMPLEMENTED; } -VOID -NTAPI -ConMgrProcessInputLine(VOID) -{ - ASSERT(FALSE); -} - NTSTATUS NTAPI ConMgrHandleEvent(IN ULONG EventCode, Modified: trunk/reactos/drivers/sac/driver/data.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/data.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/drivers/sac/driver/data.c [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/data.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -238,7 +238,7 @@ KeInitializeTimer(&DeviceExtension->Timer); KeInitializeDpc(&DeviceExtension->Dpc, TimerDpcRoutine, DeviceExtension); KeInitializeSpinLock(&DeviceExtension->Lock); - KeInitializeEvent(&DeviceExtension->Event, SynchronizationEvent, 0); + KeInitializeEvent(&DeviceExtension->Event, SynchronizationEvent, FALSE); InitializeListHead(&DeviceExtension->List); /* Attempt to enable HDL support */ @@ -317,8 +317,8 @@ DeviceExtension->PriorityFail = TRUE; /* Initialize rundown and wait for the thread to do it */ - KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, 0); - KeSetEvent(&DeviceExtension->Event, DeviceExtension->PriorityBoost, 0); + KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, FALSE); + KeSetEvent(&DeviceExtension->Event, DeviceExtension->PriorityBoost, FALSE); Status = KeWaitForSingleObject(&DeviceExtension->RundownEvent, Executive, KernelMode, Modified: trunk/reactos/drivers/sac/driver/dispatch.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/dispatch.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/drivers/sac/driver/dispatch.c [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/dispatch.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -11,6 +11,8 @@ #include "sacdrv.h" /* GLOBALS *******************************************************************/ + +LONG TimerDpcCount; /* FUNCTIONS *****************************************************************/ @@ -61,7 +63,48 @@ IN PVOID SystemArgument1, IN PVOID SystemArgument2) { + HEADLESS_RSP_GET_BYTE ByteValue; + ULONG ValueSize; + BOOLEAN GotChar; + NTSTATUS Status; + PSAC_DEVICE_EXTENSION SacExtension; + /* Update our counter */ + _InterlockedExchangeAdd(&TimerDpcCount, 1); + + /* Set defaults and loop for new characters */ + GotChar = FALSE; + ValueSize = sizeof(ByteValue); + do + { + /* Ask the kernel for a byte */ + Status = HeadlessDispatch(HeadlessCmdGetByte, + NULL, + 0, + &ByteValue, + &ValueSize); + + /* Break out if there's nothing interesting */ + if (!NT_SUCCESS(Status)) break; + if (!ByteValue.Value) break; + + /* Update the serial port buffer */ + SerialPortBuffer[SerialPortProducerIndex] = ByteValue.Value; + GotChar = TRUE; + + /* Update the index, let it roll-over if needed */ + _InterlockedExchange(&SerialPortProducerIndex, + (SerialPortProducerIndex + 1) & + (SAC_SERIAL_PORT_BUFFER_SIZE - 1)); + } while (ByteValue.Value); + + /* Did we get anything */ + if (GotChar) + { + /* Signal the worker thread that there is work to do */ + SacExtension = DeferredContext; + KeSetEvent(&SacExtension->Event, SacExtension->PriorityBoost, FALSE); + } } VOID Modified: trunk/reactos/drivers/sac/driver/sacdrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/sacdrv.h?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/drivers/sac/driver/sacdrv.h [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/sacdrv.h [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -156,6 +156,7 @@ #define SAC_MAX_CHANNELS 10 #define SAC_SERIAL_PORT_BUFFER_SIZE 1024 // 1KB #define SAC_MAX_MESSAGES 200 +#define SAC_VTUTF8_COL_WIDTH 80 // // Channel flags @@ -766,6 +767,35 @@ IN PSAC_CHANNEL Channel ); +NTSTATUS +NTAPI +ChannelIWrite( + IN PSAC_CHANNEL Channel, + IN PCHAR Buffer, + IN ULONG BufferSize +); + +UCHAR +NTAPI +ChannelIReadLast( + IN PSAC_CHANNEL Channel +); + +ULONG +NTAPI +ChannelIBufferLength( + IN PSAC_CHANNEL Channel +); + +NTSTATUS +NTAPI +ChannelIRead( + IN PSAC_CHANNEL Channel, + IN PCHAR Buffer, + IN ULONG BufferSize, + IN OUT PULONG ResultBufferSize +); + // // RAW Channel Table // @@ -901,6 +931,7 @@ extern KMUTEX CurrentChannelLock; extern LONG CurrentChannelRefCount; extern PCHAR SerialPortBuffer; +extern LONG SerialPortConsumerIndex, SerialPortProducerIndex; extern PCHAR Utf8ConversionBuffer; extern ULONG Utf8ConversionBufferSize; Modified: trunk/reactos/drivers/sac/driver/util.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/util.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/drivers/sac/driver/util.c [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/util.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -14,7 +14,9 @@ PCHAR Utf8ConversionBuffer; ULONG Utf8ConversionBufferSize = PAGE_SIZE; + PSAC_MACHINE_INFO MachineInformation; + PVOID RequestSacCmdEventObjectBody; PKEVENT RequestSacCmdEventWaitObjectBody; PVOID RequestSacCmdSuccessEventObjectBody; Modified: trunk/reactos/include/reactos/libs/cportlib/cportlib.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/libs/cportlib/cportlib.h?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/include/reactos/libs/cportlib/cportlib.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/libs/cportlib/cportlib.h [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -71,7 +71,8 @@ CpGetByte( IN PCPPORT Port, OUT PUCHAR Byte, - IN BOOLEAN Wait + IN BOOLEAN Wait, + IN BOOLEAN Poll ); VOID Modified: trunk/reactos/lib/cportlib/cport.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cportlib/cport.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/lib/cportlib/cport.c [iso-8859-1] (original) +++ trunk/reactos/lib/cportlib/cport.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -255,7 +255,8 @@ NTAPI CpGetByte(IN PCPPORT Port, OUT PUCHAR Byte, - IN BOOLEAN Wait) + IN BOOLEAN Wait, + IN BOOLEAN Poll) { UCHAR Lsr; ULONG LimitCount = Wait ? TIMEOUT_COUNT : 1; @@ -277,6 +278,9 @@ return CP_GET_ERROR; } + /* If only polling was requested by caller, return now */ + if (Poll) return CP_GET_SUCCESS; + /* Otherwise read the byte and return it */ *Byte = READ_PORT_UCHAR(Port->Address + RECEIVE_BUFFER_REGISTER); Modified: trunk/reactos/ntoskrnl/ex/hdlsterm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/hdlsterm.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/ex/hdlsterm.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ex/hdlsterm.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -262,6 +262,7 @@ PHEADLESS_RSP_QUERY_INFO HeadlessInfo; PHEADLESS_CMD_PUT_STRING PutString; PHEADLESS_CMD_ENABLE_TERMINAL EnableTerminal; + PHEADLESS_RSP_GET_BYTE GetByte; NTSTATUS Status = STATUS_NOT_IMPLEMENTED; ASSERT(HeadlessGlobals != NULL); // ASSERT(HeadlessGlobals->PageLockHandle != NULL); @@ -328,8 +329,18 @@ Status = STATUS_SUCCESS; break; - case HeadlessCmdClearDisplay: - break; + case HeadlessCmdClearDisplay: + + /* Send the VT100 claer screen command if the terminal is enabled */ + if (HeadlessGlobals->TerminalEnabled) + { + HdlspSendStringAtBaud((PUCHAR)"\033[2J"); + } + + /* Return success either way */ + Status = STATUS_SUCCESS; + break; + case HeadlessCmdClearToEndOfDisplay: break; case HeadlessCmdClearToEndOfLine: @@ -344,8 +355,46 @@ break; case HeadlessCmdTerminalPoll: break; - case HeadlessCmdGetByte: - break; + + case HeadlessCmdGetByte: + + /* Make sure the caller passed valid data */ + if (!(OutputBuffer) || + !(OutputBufferSize) || + (*OutputBufferSize < sizeof(*GetByte))) + { + DPRINT1("Invalid buffer\n"); + Status = STATUS_INVALID_PARAMETER; + break; + } + + /* Make sure the terminal is enabled */ + GetByte = OutputBuffer; + if (HeadlessGlobals->TerminalEnabled) + { + /* Poll if something is on the wire */ + if (InbvPortPollOnly(HeadlessGlobals->TerminalPort)) + { + /* If so, read it */ + InbvPortGetByte(HeadlessGlobals->TerminalPort, + &GetByte->Value); + } + else + { + /* Nothing is there, return 0 */ + GetByte->Value = 0; + } + } + else + { + /* Otherwise return nothing */ + GetByte->Value = 0; + } + + /* Return success either way */ + Status = STATUS_SUCCESS; + break; + case HeadlessCmdGetLine: break; case HeadlessCmdStartBugCheck: Modified: trunk/reactos/ntoskrnl/inbv/inbvport.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/inbv/inbvport.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/inbv/inbvport.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/inbv/inbvport.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -22,6 +22,25 @@ }; /* FUNCTIONS *****************************************************************/ + +BOOLEAN +NTAPI +InbvPortPollOnly(IN ULONG PortId) +{ + UCHAR Dummy; + + /* Poll a byte from the port */ + return CpGetByte(&Port[PortId], &Dummy, FALSE, TRUE) == CP_GET_SUCCESS; +} + +BOOLEAN +NTAPI +InbvPortGetByte(IN ULONG PortId, + OUT PUCHAR Char) +{ + /* Read a byte from the port */ + return CpGetByte(&Port[PortId], Char, TRUE, FALSE) == CP_GET_SUCCESS; +} VOID NTAPI Modified: trunk/reactos/ntoskrnl/include/internal/hdl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/hdl.h?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/hdl.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/hdl.h [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -192,6 +192,11 @@ UCHAR String[1]; } HEADLESS_CMD_PUT_STRING, *PHEADLESS_CMD_PUT_STRING; +typedef struct _HEADLESS_RSP_GET_BYTE +{ + UCHAR Value; +} HEADLESS_RSP_GET_BYTE, *PHEADLESS_RSP_GET_BYTE; + NTSTATUS NTAPI HeadlessDispatch( Modified: trunk/reactos/ntoskrnl/include/internal/inbv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/inbv.h?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/inbv.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/inbv.h [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -107,4 +107,17 @@ IN BOOLEAN IsMMIODevice ); +BOOLEAN +NTAPI +InbvPortPollOnly( + IN ULONG PortId +); + +BOOLEAN +NTAPI +InbvPortGetByte( + IN ULONG PortId, + OUT PUCHAR Char +); + extern BOOLEAN InbvBootDriverInstalled; Modified: trunk/reactos/ntoskrnl/kd/i386/kdbg.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kd/i386/kdbg.c?rev=59772&r1=59771&r2=59772&view=diff ============================================================================== --- trunk/reactos/ntoskrnl/kd/i386/kdbg.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/kd/i386/kdbg.c [iso-8859-1] Sun Aug 18 17:47:19 2013 @@ -136,7 +136,7 @@ IN PCPPORT PortInformation, OUT PUCHAR ByteReceived) { - return (CpGetByte(PortInformation, ByteReceived, FALSE) == CP_GET_SUCCESS); + return (CpGetByte(PortInformation, ByteReceived, FALSE, TRUE) == CP_GET_SUCCESS); } VOID