2 Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
3 provided by Ps2KbdCtrller.c.
5 Copyright (c) 2006 - 2009, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "Ps2Keyboard.h"
20 Check keyboard for given key value.
22 @param This Point to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
24 @retval EFI_SUCCESS success check keyboard value
25 @retval !EFI_SUCCESS Fail to get char from keyboard
29 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
32 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
34 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
37 // If ready to read next key, check it
39 if (ConsoleIn
->Key
.ScanCode
== SCAN_NULL
&& ConsoleIn
->Key
.UnicodeChar
== 0x00) {
40 return KeyGetchar (ConsoleIn
);
47 Judge whether is a registed key
49 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
50 state data for the key that was registered.
51 @param InputData A pointer to a buffer that is filled in with the keystroke
52 state data for the key that was pressed.
54 @retval TRUE Key be pressed matches a registered key.
55 @retval FLASE Match failed.
60 IN EFI_KEY_DATA
*RegsiteredData
,
61 IN EFI_KEY_DATA
*InputData
65 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
67 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
68 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
73 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
75 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
76 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
79 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
80 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
89 Reads the next keystroke from the input device. The WaitForKey Event can
90 be used to test for existance of a keystroke via WaitForEvent () call.
92 @param ConsoleInDev Ps2 Keyboard private structure
93 @param KeyData A pointer to a buffer that is filled in with the keystroke
94 state data for the key that was pressed.
97 @retval EFI_SUCCESS The keystroke information was returned.
98 @retval EFI_NOT_READY There was no keystroke data availiable.
99 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
101 @retval EFI_INVALID_PARAMETER KeyData is NULL.
105 KeyboardReadKeyStrokeWorker (
106 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
,
107 OUT EFI_KEY_DATA
*KeyData
114 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
115 EFI_KEY_DATA OriginalKeyData
;
117 if (KeyData
== NULL
) {
118 return EFI_INVALID_PARAMETER
;
122 // Enter critical section
124 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
126 if (ConsoleInDev
->KeyboardErr
) {
127 gBS
->RestoreTPL (OldTpl
);
128 return EFI_DEVICE_ERROR
;
131 // If there's no key, just return
133 Status
= KeyboardCheckForKey (&ConsoleInDev
->ConIn
);
134 if (EFI_ERROR (Status
)) {
135 gBS
->RestoreTPL (OldTpl
);
136 return EFI_NOT_READY
;
139 CopyMem (&KeyData
->Key
, &ConsoleInDev
->Key
, sizeof (EFI_INPUT_KEY
));
141 ConsoleInDev
->Key
.ScanCode
= SCAN_NULL
;
142 ConsoleInDev
->Key
.UnicodeChar
= 0x0000;
143 CopyMem (&KeyData
->KeyState
, &ConsoleInDev
->KeyState
, sizeof (EFI_KEY_STATE
));
145 ConsoleInDev
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
146 ConsoleInDev
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
147 gBS
->RestoreTPL (OldTpl
);
149 //Switch the control value to their original characters. In KeyGetchar() the CTRL-Alpha characters have been switched to
150 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.
152 CopyMem (&OriginalKeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
153 if (ConsoleInDev
->Ctrled
) {
154 if (OriginalKeyData
.Key
.UnicodeChar
>= 0x01 && OriginalKeyData
.Key
.UnicodeChar
<= 0x1A) {
155 if (ConsoleInDev
->CapsLock
) {
156 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ L
'A' - 1);
158 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ L
'a' - 1);
163 // Invoke notification functions if exist
165 for (Link
= ConsoleInDev
->NotifyList
.ForwardLink
; Link
!= &ConsoleInDev
->NotifyList
; Link
= Link
->ForwardLink
) {
168 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
170 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
172 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &OriginalKeyData
)) {
173 CurrentNotify
->KeyNotificationFn (&OriginalKeyData
);
181 Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()
183 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
184 @param ExtendedVerification Indicate that the driver may perform a more
185 exhaustive verification operation of the device during
186 reset, now this par is ignored in this driver
192 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
193 IN BOOLEAN ExtendedVerification
197 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
200 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
201 if (ConsoleIn
->KeyboardErr
) {
202 return EFI_DEVICE_ERROR
;
205 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
207 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
,
208 ConsoleIn
->DevicePath
212 // Enter critical section
214 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
217 // Call InitKeyboard to initialize the keyboard
219 Status
= InitKeyboard (ConsoleIn
, ExtendedVerification
);
220 if (EFI_ERROR (Status
)) {
222 // Leave critical section and return
224 gBS
->RestoreTPL (OldTpl
);
225 return EFI_DEVICE_ERROR
;
228 // Clear the status of ConsoleIn.Key
230 ConsoleIn
->Key
.ScanCode
= SCAN_NULL
;
231 ConsoleIn
->Key
.UnicodeChar
= 0x0000;
234 // Leave critical section and return
236 gBS
->RestoreTPL (OldTpl
);
239 // Report the status If a stuck key was detected
241 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
242 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
243 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
244 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_EC_STUCK_KEY
,
245 ConsoleIn
->DevicePath
249 // Report the status If keyboard is locked
251 if ((KeyReadStatusRegister (ConsoleIn
) & 0x10) == 0) {
252 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
253 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
254 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_EC_LOCKED
,
255 ConsoleIn
->DevicePath
263 Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().
265 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
266 @param Key The output buffer for key value
268 @retval EFI_SUCCESS success to read key stroke
272 KeyboardReadKeyStroke (
273 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
274 OUT EFI_INPUT_KEY
*Key
278 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
279 EFI_KEY_DATA KeyData
;
281 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
282 Status
= KeyboardReadKeyStrokeWorker (ConsoleIn
, &KeyData
);
283 if (EFI_ERROR (Status
)) {
287 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
293 Event notification function for SIMPLE_TEXT_IN.WaitForKey event
294 Signal the event if there is key available
296 @param Event the event object
297 @param Context waitting context
308 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
310 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context
);
313 // Enter critical section
315 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
317 if (ConsoleIn
->KeyboardErr
) {
319 // Leave critical section and return
321 gBS
->RestoreTPL (OldTpl
);
325 // Someone is waiting on the keyboard event, if there's
326 // a key pending, signal the event
328 if (!EFI_ERROR (KeyboardCheckForKey (Context
))) {
329 gBS
->SignalEvent (Event
);
332 // Leave critical section and return
334 gBS
->RestoreTPL (OldTpl
);
340 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
341 Signal the event if there is key available
343 @param Event event object
344 @param Context waiting context
349 KeyboardWaitForKeyEx (
355 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
357 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context
);
358 KeyboardWaitForKey (Event
, &ConsoleInDev
->ConIn
);
363 Reset the input device and optionaly run diagnostics
365 @param This Protocol instance pointer.
366 @param ExtendedVerification Driver may perform diagnostics on reset.
368 @retval EFI_SUCCESS The device was reset.
369 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
376 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
377 IN BOOLEAN ExtendedVerification
382 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
385 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
386 if (ConsoleInDev
->KeyboardErr
) {
387 return EFI_DEVICE_ERROR
;
390 Status
= ConsoleInDev
->ConIn
.Reset (
391 &ConsoleInDev
->ConIn
,
394 if (EFI_ERROR (Status
)) {
395 return EFI_DEVICE_ERROR
;
398 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
400 ConsoleInDev
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
401 ConsoleInDev
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
403 gBS
->RestoreTPL (OldTpl
);
409 Reads the next keystroke from the input device. The WaitForKey Event can
410 be used to test for existance of a keystroke via WaitForEvent () call.
413 @param This Protocol instance pointer.
414 @param KeyData A pointer to a buffer that is filled in with the keystroke
415 state data for the key that was pressed.
417 @retval EFI_SUCCESS The keystroke information was returned.
418 @retval EFI_NOT_READY There was no keystroke data availiable.
419 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
421 @retval EFI_INVALID_PARAMETER KeyData is NULL.
426 KeyboardReadKeyStrokeEx (
427 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
428 OUT EFI_KEY_DATA
*KeyData
432 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
434 if (KeyData
== NULL
) {
435 return EFI_INVALID_PARAMETER
;
438 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
439 return KeyboardReadKeyStrokeWorker (ConsoleInDev
, KeyData
);
444 Set certain state for the input device.
446 @param This Protocol instance pointer.
447 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
448 state for the input device.
450 @retval EFI_SUCCESS The device state was set successfully.
451 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
452 not have the setting adjusted.
453 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
454 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
460 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
461 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
466 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
469 if (KeyToggleState
== NULL
) {
470 return EFI_INVALID_PARAMETER
;
473 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
476 // Enter critical section
478 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
480 if (ConsoleInDev
->KeyboardErr
) {
481 Status
= EFI_DEVICE_ERROR
;
485 if (((ConsoleInDev
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
486 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
487 Status
= EFI_UNSUPPORTED
;
492 // Update the status light
494 ConsoleInDev
->ScrollLock
= FALSE
;
495 ConsoleInDev
->NumLock
= FALSE
;
496 ConsoleInDev
->CapsLock
= FALSE
;
498 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
499 ConsoleInDev
->ScrollLock
= TRUE
;
501 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
502 ConsoleInDev
->NumLock
= TRUE
;
504 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
505 ConsoleInDev
->CapsLock
= TRUE
;
508 Status
= UpdateStatusLights (ConsoleInDev
);
509 if (EFI_ERROR (Status
)) {
510 Status
= EFI_DEVICE_ERROR
;
513 ConsoleInDev
->KeyState
.KeyToggleState
= *KeyToggleState
;
517 // Leave critical section and return
519 gBS
->RestoreTPL (OldTpl
);
526 Register a notification function for a particular keystroke for the input device.
528 @param This Protocol instance pointer.
529 @param KeyData A pointer to a buffer that is filled in with the keystroke
530 information data for the key that was pressed.
531 @param KeyNotificationFunction Points to the function to be called when the key
532 sequence is typed specified by KeyData.
533 @param NotifyHandle Points to the unique handle assigned to the registered notification.
535 @retval EFI_SUCCESS The notification function was registered successfully.
536 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
537 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
542 KeyboardRegisterKeyNotify (
543 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
544 IN EFI_KEY_DATA
*KeyData
,
545 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
546 OUT EFI_HANDLE
*NotifyHandle
550 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
553 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
554 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
556 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
557 return EFI_INVALID_PARAMETER
;
560 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
563 // Enter critical section
565 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
568 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
570 for (Link
= ConsoleInDev
->NotifyList
.ForwardLink
; Link
!= &ConsoleInDev
->NotifyList
; Link
= Link
->ForwardLink
) {
573 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
575 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
577 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
578 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
579 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
580 Status
= EFI_SUCCESS
;
587 // Allocate resource to save the notification function
589 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
590 if (NewNotify
== NULL
) {
591 Status
= EFI_OUT_OF_RESOURCES
;
595 NewNotify
->Signature
= KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
596 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
597 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
598 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
599 InsertTailList (&ConsoleInDev
->NotifyList
, &NewNotify
->NotifyEntry
);
601 *NotifyHandle
= NewNotify
->NotifyHandle
;
602 Status
= EFI_SUCCESS
;
606 // Leave critical section and return
608 gBS
->RestoreTPL (OldTpl
);
614 Remove a registered notification function from a particular keystroke.
616 @param This Protocol instance pointer.
617 @param NotificationHandle The handle of the notification function being unregistered.
620 @retval EFI_SUCCESS The notification function was unregistered successfully.
621 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
626 KeyboardUnregisterKeyNotify (
627 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
628 IN EFI_HANDLE NotificationHandle
632 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
635 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
637 if (NotificationHandle
== NULL
) {
638 return EFI_INVALID_PARAMETER
;
641 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
642 return EFI_INVALID_PARAMETER
;
645 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
648 // Enter critical section
650 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
652 for (Link
= ConsoleInDev
->NotifyList
.ForwardLink
; Link
!= &ConsoleInDev
->NotifyList
; Link
= Link
->ForwardLink
) {
655 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
657 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
659 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
661 // Remove the notification function from NotifyList and free resources
663 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
665 gBS
->FreePool (CurrentNotify
);
666 Status
= EFI_SUCCESS
;
672 // Can not find the specified Notification Handle
674 Status
= EFI_INVALID_PARAMETER
;
677 // Leave critical section and return
679 gBS
->RestoreTPL (OldTpl
);