0,\r
(EFI_SIMPLE_TEXT_INPUT_PROTOCOL **) NULL,\r
0,\r
+ {\r
+ ConSplitterTextInResetEx,\r
+ ConSplitterTextInReadKeyStrokeEx,\r
+ (EFI_EVENT) NULL,\r
+ ConSplitterTextInSetState,\r
+ ConSplitterTextInRegisterKeyNotify,\r
+ ConSplitterTextInUnregisterKeyNotify\r
+ },\r
+ 0,\r
+ (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **) NULL,\r
+ 0,\r
+ {\r
+ (struct _LIST_ENTRY *) NULL,\r
+ (struct _LIST_ENTRY *) NULL\r
+ },\r
\r
{\r
ConSplitterSimplePointerReset,\r
&mConIn.VirtualHandle,\r
&gEfiSimpleTextInProtocolGuid,\r
&mConIn.TextIn,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &mConIn.TextInEx,\r
&gEfiSimplePointerProtocolGuid,\r
&mConIn.SimplePointer,\r
&gEfiPrimaryConsoleInDeviceGuid,\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Buffer for Simple Text Input Ex Protocol\r
+ // \r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+ &ConInPrivate->TextInExListCount,\r
+ (VOID **) &ConInPrivate->TextInExList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ ConSplitterTextInWaitForKey,\r
+ ConInPrivate,\r
+ &ConInPrivate->TextInEx.WaitForKeyEx\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InitializeListHead (&ConInPrivate->NotifyList); \r
+\r
+\r
ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode;\r
\r
Status = ConSplitterGrowBuffer (\r
{\r
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
return Status;\r
}\r
\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &TextInEx,\r
+ This->DriverBindingHandle,\r
+ mConIn.VirtualHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = ConSplitterTextInExAddDevice (&mConIn, TextInEx);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } \r
+\r
return ConSplitterTextInAddDevice (&mConIn, TextIn);\r
}\r
\r
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx;\r
if (NumberOfChildren == 0) {\r
return EFI_SUCCESS;\r
}\r
\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID **) &TextInEx,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = ConSplitterTextInExDeleteDevice (&mConIn, TextInEx);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ \r
Status = ConSplitterStop (\r
This,\r
ControllerHandle,\r
return EFI_NOT_FOUND;\r
}\r
\r
+EFI_STATUS\r
+ConSplitterTextInExAddDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // If the TextInEx List is full, enlarge it by calling growbuffer().\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
+ &Private->TextInExListCount,\r
+ (VOID **) &Private->TextInExList\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+ //\r
+ // Add the new text-in device data structure into the Text In List.\r
+ //\r
+ Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
+ Private->CurrentNumberOfExConsoles++;\r
+\r
+ //\r
+ // Extra CheckEvent added to reduce the double CheckEvent() in UI.c\r
+ //\r
+ gBS->CheckEvent (TextInEx->WaitForKeyEx);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ConSplitterTextInExDeleteDevice (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
+ )\r
+{\r
+ UINTN Index;\r
+ //\r
+ // Remove the specified text-in device data structure from the Text In List,\r
+ // and rearrange the remaining data structures in the Text In List.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ if (Private->TextInExList[Index] == TextInEx) {\r
+ for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
+ Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
+ }\r
+\r
+ Private->CurrentNumberOfExConsoles--;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
EFI_STATUS\r
ConSplitterSimplePointerAddDevice (\r
IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
}\r
}\r
\r
+\r
+STATIC\r
+BOOLEAN\r
+IsKeyRegistered (\r
+ IN EFI_KEY_DATA *RegsiteredData,\r
+ IN EFI_KEY_DATA *InputData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+ RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was registered.\r
+ InputData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+Returns:\r
+ TRUE - Key be pressed matches a registered key.\r
+ FLASE - Match failed. \r
+ \r
+--*/\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+ \r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE; \r
+ } \r
+ \r
+ //\r
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+ //\r
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+ return FALSE; \r
+ } \r
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+ return FALSE; \r
+ } \r
+ \r
+ return TRUE;\r
+\r
+}\r
+\r
+//\r
+// Simple Text Input Ex protocol functions\r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInResetEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reset the input device and optionaly run diagnostics\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ ExtendedVerification - Driver may perform diagnostics on reset.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The device was reset.\r
+ EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ not be reset.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS ReturnStatus;\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ UINTN Index;\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Private->KeyEventSignalState = FALSE;\r
+\r
+ //\r
+ // return the worst status met\r
+ //\r
+ for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->Reset (\r
+ Private->TextInExList[Index],\r
+ ExtendedVerification\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
+ }\r
+\r
+ return ReturnStatus;\r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInReadKeyStrokeEx (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Reads the next keystroke from the input device. The WaitForKey Event can \r
+ be used to test for existance of a keystroke via WaitForEvent () call.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ state data for the key that was pressed.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The keystroke information was returned.\r
+ EFI_NOT_READY - There was no keystroke data availiable.\r
+ EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
+ hardware errors.\r
+ EFI_INVALID_PARAMETER - KeyData is NULL. \r
+\r
+--*/\r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ EFI_KEY_DATA CurrentKeyData;\r
+\r
+ \r
+ if (KeyData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+ if (Private->PasswordEnabled) {\r
+ //\r
+ // If StdIn Locked return not ready\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Private->KeyEventSignalState = FALSE;\r
+\r
+ KeyData->Key.UnicodeChar = 0;\r
+ KeyData->Key.ScanCode = SCAN_NULL;\r
+\r
+ //\r
+ // if no physical console input device exists, return EFI_NOT_READY;\r
+ // if any physical console input device has key input,\r
+ // return the key and EFI_SUCCESS.\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
+ Private->TextInExList[Index],\r
+ &CurrentKeyData\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_READY; \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInSetState (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Set certain state for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
+ state for the input device.\r
+ \r
+ Returns: \r
+ EFI_SUCCESS - The device state was set successfully.\r
+ EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
+ not have the setting adjusted.\r
+ EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
+ EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+\r
+--*/ \r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ if (KeyToggleState == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists, return EFI_SUCCESS;\r
+ // otherwise return the status of setting state of physical console input device\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->SetState (\r
+ Private->TextInExList[Index],\r
+ KeyToggleState\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS; \r
+\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInRegisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_KEY_DATA *KeyData,\r
+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
+ OUT EFI_HANDLE *NotifyHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Register a notification function for a particular keystroke for the input device.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer.\r
+ KeyData - A pointer to a buffer that is filled in with the keystroke \r
+ information data for the key that was pressed.\r
+ KeyNotificationFunction - Points to the function to be called when the key \r
+ sequence is typed specified by KeyData. \r
+ NotifyHandle - Points to the unique handle assigned to the registered notification. \r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was registered successfully.\r
+ EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
+ EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
+ \r
+--*/ \r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *NewNotify;\r
+ LIST_ENTRY *Link;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify; \r
+ \r
+\r
+ if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists, \r
+ // return EFI_SUCCESS directly.\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles <= 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
+ //\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (\r
+ Link, \r
+ TEXT_IN_EX_SPLITTER_NOTIFY, \r
+ NotifyEntry, \r
+ TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE\r
+ );\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
+ *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Allocate resource to save the notification function\r
+ // \r
+ NewNotify = (TEXT_IN_EX_SPLITTER_NOTIFY *) AllocateZeroPool (sizeof (TEXT_IN_EX_SPLITTER_NOTIFY));\r
+ if (NewNotify == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
+ if (NewNotify->NotifyHandleList == NULL) {\r
+ gBS->FreePool (NewNotify);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE; \r
+ NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+ \r
+ //\r
+ // Return the wrong status of registering key notify of \r
+ // physical console input device if meet problems\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->RegisterKeyNotify (\r
+ Private->TextInExList[Index],\r
+ KeyData,\r
+ KeyNotificationFunction,\r
+ &NewNotify->NotifyHandleList[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (NewNotify->NotifyHandleList);\r
+ gBS->FreePool (NewNotify);\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
+ // \r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &NewNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+ \r
+ *NotifyHandle = NewNotify->NotifyHandle; \r
+ \r
+ return EFI_SUCCESS; \r
+ \r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ConSplitterTextInUnregisterKeyNotify (\r
+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
+ IN EFI_HANDLE NotificationHandle\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Remove a registered notification function from a particular keystroke.\r
+\r
+ Arguments:\r
+ This - Protocol instance pointer. \r
+ NotificationHandle - The handle of the notification function being unregistered.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The notification function was unregistered successfully.\r
+ EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
+ EFI_NOT_FOUND - Can not find the matching entry in database. \r
+ \r
+--*/ \r
+{\r
+ TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
+ LIST_ENTRY *Link; \r
+\r
+ if (NotificationHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NotificationHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // if no physical console input device exists, \r
+ // return EFI_SUCCESS directly.\r
+ //\r
+ if (Private->CurrentNumberOfExConsoles <= 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = CR (Link, TEXT_IN_EX_SPLITTER_NOTIFY, NotifyEntry, TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE);\r
+ if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
+ Private->TextInExList[Index], \r
+ CurrentNotify->NotifyHandleList[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } \r
+ }\r
+ RemoveEntryList (&CurrentNotify->NotifyEntry); \r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ CurrentNotify->NotifyHandle,\r
+ &gSimpleTextInExNotifyGuid,\r
+ NULL,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (CurrentNotify->NotifyHandleList);\r
+ gBS->FreePool (CurrentNotify);\r
+ return EFI_SUCCESS; \r
+ } \r
+ }\r
+\r
+ return EFI_NOT_FOUND; \r
+ \r
+}\r
+\r
+\r
+\r
EFI_STATUS\r
EFIAPI\r
ConSplitterSimplePointerReset (\r