[CPORTLIB/KDBG/FREELDR]: Fix CpGetByte and its callers -- it takes a 4th parameter...
authorAlex Ionescu <aionescu@gmail.com>
Sun, 18 Aug 2013 17:47:19 +0000 (17:47 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 18 Aug 2013 17:47:19 +0000 (17:47 +0000)
[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.

svn path=/trunk/; revision=59772

14 files changed:
reactos/boot/freeldr/freeldr/comm/rs232.c
reactos/boot/freeldr/freeldr/windows/headless.c
reactos/drivers/sac/driver/conmgr.c
reactos/drivers/sac/driver/data.c
reactos/drivers/sac/driver/dispatch.c
reactos/drivers/sac/driver/sacdrv.h
reactos/drivers/sac/driver/util.c
reactos/include/reactos/libs/cportlib/cportlib.h
reactos/lib/cportlib/cport.c
reactos/ntoskrnl/ex/hdlsterm.c
reactos/ntoskrnl/inbv/inbvport.c
reactos/ntoskrnl/include/internal/hdl.h
reactos/ntoskrnl/include/internal/inbv.h
reactos/ntoskrnl/kd/i386/kdbg.c

index 347ca09..7f0d9d8 100644 (file)
@@ -100,7 +100,7 @@ BOOLEAN Rs232PortGetByte(PUCHAR ByteReceived)
     if (PortInitialized == FALSE)
         return FALSE;
 
-    return (CpGetByte(&Rs232ComPort, ByteReceived, TRUE) == CP_GET_SUCCESS);
+    return (CpGetByte(&Rs232ComPort, ByteReceived, TRUE, FALSE) == CP_GET_SUCCESS);
 }
 
 /*
index 40db235..515593a 100644 (file)
@@ -143,7 +143,7 @@ BOOLEAN
 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 @@ WinLdrPortPollOnly(IN ULONG PortId)
 {
     UCHAR Dummy;
 
-    return CpGetByte(&Port[PortId], &Dummy, FALSE) == CP_GET_SUCCESS;
+    return CpGetByte(&Port[PortId], &Dummy, FALSE, TRUE) == CP_GET_SUCCESS;
 }
 
 VOID
index b012cad..2b6406d 100644 (file)
@@ -27,76 +27,10 @@ PSAC_CHANNEL SacChannel;
 ULONG ExecutePostConsumerCommand;
 PSAC_CHANNEL ExecutePostConsumerCommandData;
 
-/* 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);
+BOOLEAN InputInEscape, InputInEscTab, ConMgrLastCharWasCR;
+CHAR InputBuffer[80];
 
-        /* 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;
-    }
-}
+/* FUNCTIONS *****************************************************************/
 
 VOID
 NTAPI
@@ -512,21 +446,327 @@ ConMgrChannelOWrite(IN PSAC_CHANNEL Channel,
     return Status;
 }
 
-NTSTATUS
+VOID
 NTAPI
-ConMgrGetChannelCloseMessage(IN PSAC_CHANNEL Channel,
-                             IN NTSTATUS CloseStatus,
-                             OUT PWCHAR OutputBuffer)
+ConMgrProcessInputLine(VOID)
 {
     ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
 }
 
+#define Nothing 0
+
 VOID
 NTAPI
-ConMgrProcessInputLine(VOID)
+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,
+                             IN NTSTATUS CloseStatus,
+                             OUT PWCHAR OutputBuffer)
 {
     ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
 }
 
 NTSTATUS
index 14e4b74..11fff65 100644 (file)
@@ -238,7 +238,7 @@ InitializeDeviceData(IN PDEVICE_OBJECT DeviceObject)
     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 @@ InitializeDeviceData(IN PDEVICE_OBJECT DeviceObject)
         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,
index 1af10f5..44ade23 100644 (file)
@@ -12,6 +12,8 @@
 
 /* GLOBALS *******************************************************************/
 
+LONG TimerDpcCount;
+
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS
@@ -61,7 +63,48 @@ TimerDpcRoutine(IN PKDPC Dpc,
                 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
index f9e4daa..b2c697e 100644 (file)
 #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 @@ ChannelDestroy(
     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 PSAC_MESSAGE_ENTRY GlobalMessageTable;
 extern KMUTEX CurrentChannelLock;
 extern LONG CurrentChannelRefCount;
 extern PCHAR SerialPortBuffer;
+extern LONG SerialPortConsumerIndex, SerialPortProducerIndex;
 extern PCHAR Utf8ConversionBuffer;
 extern ULONG Utf8ConversionBufferSize;
 
index c32f764..4c64e58 100644 (file)
@@ -14,7 +14,9 @@
 
 PCHAR Utf8ConversionBuffer;
 ULONG Utf8ConversionBufferSize = PAGE_SIZE;
+
 PSAC_MACHINE_INFO MachineInformation;
+
 PVOID RequestSacCmdEventObjectBody;
 PKEVENT RequestSacCmdEventWaitObjectBody;
 PVOID RequestSacCmdSuccessEventObjectBody;
index ef62f54..9310ea4 100644 (file)
@@ -71,7 +71,8 @@ NTAPI
 CpGetByte(
     IN  PCPPORT Port,
     OUT PUCHAR  Byte,
-    IN  BOOLEAN Wait
+    IN  BOOLEAN Wait,
+    IN BOOLEAN Poll
 );
 
 VOID
index 8e493dd..4cad5b5 100644 (file)
@@ -255,7 +255,8 @@ USHORT
 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 @@ CpGetByte(IN  PCPPORT Port,
                 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);
 
index 20c7134..41c5171 100644 (file)
@@ -262,6 +262,7 @@ HdlspDispatch(IN HEADLESS_CMD Command,
     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 @@ HdlspDispatch(IN HEADLESS_CMD Command,
             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 @@ HdlspDispatch(IN HEADLESS_CMD Command,
                        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:
index 5f58cff..d0509be 100644 (file)
@@ -23,6 +23,25 @@ CPPORT Port[4] =
 
 /* 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
 InbvPortEnableFifo(IN ULONG   PortId,
index 073f1b9..2bd0b2f 100644 (file)
@@ -192,6 +192,11 @@ typedef struct _HEADLESS_CMD_PUT_STRING
        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(
index d8446aa..867c39d 100644 (file)
@@ -107,4 +107,17 @@ InbvPortInitialize(
        IN BOOLEAN IsMMIODevice
 );
 
+BOOLEAN
+NTAPI
+InbvPortPollOnly(
+    IN ULONG PortId
+);
+
+BOOLEAN
+NTAPI
+InbvPortGetByte(
+    IN ULONG PortId,
+    OUT PUCHAR Char
+);
+
 extern BOOLEAN InbvBootDriverInstalled;
index 93084d6..0607112 100644 (file)
@@ -136,7 +136,7 @@ KdPortGetByteEx(
     IN PCPPORT PortInformation,
     OUT PUCHAR ByteReceived)
 {
-    return (CpGetByte(PortInformation, ByteReceived, FALSE) == CP_GET_SUCCESS);
+    return (CpGetByte(PortInformation, ByteReceived, FALSE, TRUE) == CP_GET_SUCCESS);
 }
 
 VOID