Implement console input Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.c Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xencons.c _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.c --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.c 2005-05-16 22:21:00 UTC (rev 15363) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.c 2005-05-16 22:42:53 UTC (rev 15364) @@ -132,6 +132,7 @@
i386TrapSaveDRHook = XenTrapSaveDR; HYPERVISOR_set_trap_table(trap_table);
+ XenConsInit(); XenCtrlIfRegisterReceiver(CMSG_SHUTDOWN, XenShutdownHandler);
/* Ready to receive events now */ @@ -196,20 +197,6 @@ printf(routine " unimplemented. Shutting down\n"); \ XenDie()
-BOOL -XenConsKbHit() - { - XEN_UNIMPLEMENTED("XenConsKbHit"); - return FALSE; - } - -int -XenConsGetCh() - { - XEN_UNIMPLEMENTED("XenConsGetCh"); - return 0; - } - VOID XenVideoSetTextCursorPosition(ULONG X, ULONG Y) { _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h 2005-05-16 22:21:00 UTC (rev 15363) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h 2005-05-16 22:42:53 UTC (rev 15364) @@ -50,6 +50,7 @@
VOID XenEvtchnDisableEvents(); VOID XenEvtchnEnableEvents();
+VOID XenConsInit(); VOID XenConsPutChar(int Ch); BOOL XenConsKbHit(); int XenConsGetCh(); _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xencons.c --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xencons.c 2005-05-16 22:21:00 UTC (rev 15363) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xencons.c 2005-05-16 22:42:53 UTC (rev 15364) @@ -41,6 +41,7 @@
*/
#include "freeldr.h" +#include "keycodes.h" #include "machxen.h"
#include <rosxen.h> @@ -61,6 +62,15 @@ static char OutputBuffer[OUTPUT_BUFFER_SIZE]; static unsigned OutputPtr = 0;
+#define INPUT_BUFFER_SIZE 64 +static int InputBuffer[INPUT_BUFFER_SIZE]; +static unsigned InputCount = 0; + +#define ESC_SEQ_TIMEOUT 200000000 /* in nanosec, 0.2 sec */ +static UCHAR InputEscSeq[4]; +static unsigned InputEscSeqCount = 0; +static ULONGLONG InputEscSeqTime = 0; + VOID XenConsFlush() { @@ -138,4 +148,157 @@ } }
+static void +XenConsGetTime(PULONGLONG Now) +{ + ULONG ShadowTimeVersion; + + do + { + ShadowTimeVersion = XenSharedInfo->time_version2; + *Now = XenSharedInfo->system_time; + } + while (ShadowTimeVersion != XenSharedInfo->time_version1); +} + +static void +XenConsCheckInputEscSequence() +{ + static struct + { + char *EscSequence; + int Key; + } + KnownSequences[] = + { + { "\033[A", KEY_UP }, + { "\033[B", KEY_DOWN }, + }; + unsigned i; + ULONGLONG Now; + + if (0 != InputEscSeqCount) + { + XenConsGetTime(&Now); + if (InputEscSeqTime + ESC_SEQ_TIMEOUT <= Now + || InputEscSeqCount == sizeof(InputEscSeq) / sizeof(InputEscSeq[0])) + { + for (i = 0; i < sizeof(InputEscSeq) / sizeof(InputEscSeq[0]); i++) + { + if (InputCount < INPUT_BUFFER_SIZE) + { + InputBuffer[InputCount++] = InputEscSeq[i]; + } + } + InputEscSeqCount = 0; + } + else + { + for (i = 0; i < sizeof(KnownSequences) / sizeof(KnownSequences[0]); i++) + { + if (InputEscSeqCount == strlen(KnownSequences[i].EscSequence) + && 0 == memcmp(InputEscSeq, KnownSequences[i].EscSequence, + InputEscSeqCount)) + { + if (InputCount < INPUT_BUFFER_SIZE) + { + InputBuffer[InputCount++] = KnownSequences[i].Key; + } + InputEscSeqCount = 0; + break; + } + } + } + } +} + +int +XenConsGetCh() +{ + int Key; + + XenEvtchnDisableEvents(); + XenConsCheckInputEscSequence(); + while (0 == InputCount) + { + HYPERVISOR_block(); + XenEvtchnDisableEvents(); + } + Key = InputBuffer[0]; + InputCount--; + if (0 != InputCount) + { + memmove(InputBuffer, InputBuffer + 1, InputCount * sizeof(int)); + } + XenEvtchnEnableEvents(); + + return Key; + } + +BOOL +XenConsKbHit() +{ + BOOL Hit; + + XenEvtchnDisableEvents(); + XenConsCheckInputEscSequence(); + Hit = (0 != InputCount); + XenEvtchnEnableEvents(); + + if (! Hit) + { + HYPERVISOR_yield(); + } + + return Hit; +} + +static void +XenConsProcessInput(unsigned Length, PUCHAR Data) +{ + unsigned i; + + XenConsCheckInputEscSequence(); + for (i = 0; i < Length; i++) + { + if (0 != InputEscSeqCount || '\033' == Data[i]) + { + InputEscSeq[InputEscSeqCount++] = Data[i]; + XenConsGetTime(&InputEscSeqTime); + XenConsCheckInputEscSequence(); + } + else + { + InputBuffer[InputCount++] = (int) Data[i]; + } + } +} + +static void +XenConsMsgHandler(ctrl_msg_t *Msg, unsigned long Id) +{ + switch (Msg->subtype) + { + case CMSG_CONSOLE_DATA: + XenConsProcessInput(Msg->length, &Msg->msg[0]); + Msg->length = 0; + break; + default: + Msg->length = 0; + break; + } + + XenCtrlIfSendResponse(Msg); +} + +VOID +XenConsInit() +{ + OutputPtr = 0; + InputCount = 0; + InputEscSeqCount = 0; + + XenCtrlIfRegisterReceiver(CMSG_CONSOLE, XenConsMsgHandler); +} + /* EOF */