2 Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
3 provided by Ps2KbdCtrller.c.
5 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
6 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 whether the EFI key buffer is empty.
22 @param Queue Pointer to instance of EFI_KEY_QUEUE.
24 @retval TRUE The EFI key buffer is empty.
25 @retval FALSE The EFI key buffer isn't empty.
29 IN EFI_KEY_QUEUE
*Queue
32 return (BOOLEAN
) (Queue
->Head
== Queue
->Tail
);
36 Read & remove one key data from the EFI key buffer.
38 @param Queue Pointer to instance of EFI_KEY_QUEUE.
39 @param KeyData Receive the key data.
41 @retval EFI_SUCCESS The key data is popped successfully.
42 @retval EFI_NOT_READY There is no key data available.
46 IN EFI_KEY_QUEUE
*Queue
,
47 OUT EFI_KEY_DATA
*KeyData OPTIONAL
50 if (IsEfikeyBufEmpty (Queue
)) {
54 // Retrieve and remove the values
56 if (KeyData
!= NULL
) {
57 CopyMem (KeyData
, &Queue
->Buffer
[Queue
->Head
], sizeof (EFI_KEY_DATA
));
59 Queue
->Head
= (Queue
->Head
+ 1) % KEYBOARD_EFI_KEY_MAX_COUNT
;
64 Push one key data to the EFI key buffer.
66 @param Queue Pointer to instance of EFI_KEY_QUEUE.
67 @param KeyData The key data to push.
71 IN EFI_KEY_QUEUE
*Queue
,
72 IN EFI_KEY_DATA
*KeyData
75 if ((Queue
->Tail
+ 1) % KEYBOARD_EFI_KEY_MAX_COUNT
== Queue
->Head
) {
77 // If Queue is full, pop the one from head.
79 PopEfikeyBufHead (Queue
, NULL
);
81 CopyMem (&Queue
->Buffer
[Queue
->Tail
], KeyData
, sizeof (EFI_KEY_DATA
));
82 Queue
->Tail
= (Queue
->Tail
+ 1) % KEYBOARD_EFI_KEY_MAX_COUNT
;
86 Judge whether is a registed key
88 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
89 state data for the key that was registered.
90 @param InputData A pointer to a buffer that is filled in with the keystroke
91 state data for the key that was pressed.
93 @retval TRUE Key be pressed matches a registered key.
94 @retval FLASE Match failed.
99 IN EFI_KEY_DATA
*RegsiteredData
,
100 IN EFI_KEY_DATA
*InputData
104 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
106 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
107 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
112 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
114 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
115 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
118 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
119 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
128 Reads the next keystroke from the input device. The WaitForKey Event can
129 be used to test for existance of a keystroke via WaitForEvent () call.
131 @param ConsoleInDev Ps2 Keyboard private structure
132 @param KeyData A pointer to a buffer that is filled in with the keystroke
133 state data for the key that was pressed.
136 @retval EFI_SUCCESS The keystroke information was returned.
137 @retval EFI_NOT_READY There was no keystroke data availiable.
138 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
140 @retval EFI_INVALID_PARAMETER KeyData is NULL.
144 KeyboardReadKeyStrokeWorker (
145 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
,
146 OUT EFI_KEY_DATA
*KeyData
153 if (KeyData
== NULL
) {
154 return EFI_INVALID_PARAMETER
;
158 // Enter critical section
160 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
162 KeyboardTimerHandler (NULL
, ConsoleInDev
);
164 if (ConsoleInDev
->KeyboardErr
) {
165 Status
= EFI_DEVICE_ERROR
;
167 Status
= PopEfikeyBufHead (&ConsoleInDev
->EfiKeyQueue
, KeyData
);
170 gBS
->RestoreTPL (OldTpl
);
175 Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()
177 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
178 @param ExtendedVerification Indicate that the driver may perform a more
179 exhaustive verification operation of the device during
180 reset, now this par is ignored in this driver
186 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
187 IN BOOLEAN ExtendedVerification
191 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
194 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
195 if (ConsoleIn
->KeyboardErr
) {
196 return EFI_DEVICE_ERROR
;
199 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
201 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
,
202 ConsoleIn
->DevicePath
206 // Enter critical section
208 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
211 // Call InitKeyboard to initialize the keyboard
213 Status
= InitKeyboard (ConsoleIn
, ExtendedVerification
);
214 if (EFI_ERROR (Status
)) {
216 // Leave critical section and return
218 gBS
->RestoreTPL (OldTpl
);
219 return EFI_DEVICE_ERROR
;
223 // Leave critical section and return
225 gBS
->RestoreTPL (OldTpl
);
228 // Report the status If a stuck key was detected
230 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
231 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
232 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
233 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_EC_STUCK_KEY
,
234 ConsoleIn
->DevicePath
238 // Report the status If keyboard is locked
240 if ((KeyReadStatusRegister (ConsoleIn
) & 0x10) == 0) {
241 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
242 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
243 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_EC_LOCKED
,
244 ConsoleIn
->DevicePath
252 Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().
254 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
255 @param Key The output buffer for key value
257 @retval EFI_SUCCESS success to read key stroke
261 KeyboardReadKeyStroke (
262 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
263 OUT EFI_INPUT_KEY
*Key
267 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
268 EFI_KEY_DATA KeyData
;
270 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
273 // Considering if the partial keystroke is enabled, there maybe a partial
274 // keystroke in the queue, so here skip the partial keystroke and get the
275 // next key from the queue
279 // If there is no pending key, then return.
281 Status
= KeyboardReadKeyStrokeWorker (ConsoleIn
, &KeyData
);
282 if (EFI_ERROR (Status
)) {
286 // If it is partial keystroke, skip it.
288 if (KeyData
.Key
.ScanCode
== SCAN_NULL
&& KeyData
.Key
.UnicodeChar
== CHAR_NULL
) {
292 // Translate the CTRL-Alpha characters to their corresponding control value
293 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
295 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
296 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
297 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
298 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') {
299 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
303 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
309 Event notification function for SIMPLE_TEXT_IN.WaitForKey event
310 Signal the event if there is key available
312 @param Event the event object
313 @param Context waitting context
324 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
325 EFI_KEY_DATA KeyData
;
327 ConsoleIn
= (KEYBOARD_CONSOLE_IN_DEV
*) Context
;
330 // Enter critical section
332 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
334 KeyboardTimerHandler (NULL
, ConsoleIn
);
336 if (!ConsoleIn
->KeyboardErr
) {
338 // WaitforKey doesn't suppor the partial key.
339 // Considering if the partial keystroke is enabled, there maybe a partial
340 // keystroke in the queue, so here skip the partial keystroke and get the
341 // next key from the queue
343 while (!IsEfikeyBufEmpty (&ConsoleIn
->EfiKeyQueue
)) {
346 &(ConsoleIn
->EfiKeyQueue
.Buffer
[ConsoleIn
->EfiKeyQueue
.Head
]),
347 sizeof (EFI_KEY_DATA
)
349 if (KeyData
.Key
.ScanCode
== SCAN_NULL
&& KeyData
.Key
.UnicodeChar
== CHAR_NULL
) {
350 PopEfikeyBufHead (&ConsoleIn
->EfiKeyQueue
, &KeyData
);
354 // if there is pending value key, signal the event.
356 gBS
->SignalEvent (Event
);
361 // Leave critical section and return
363 gBS
->RestoreTPL (OldTpl
);
367 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
368 Signal the event if there is key available
370 @param Event event object
371 @param Context waiting context
376 KeyboardWaitForKeyEx (
382 KeyboardWaitForKey (Event
, Context
);
386 Reset the input device and optionaly run diagnostics
388 @param This Protocol instance pointer.
389 @param ExtendedVerification Driver may perform diagnostics on reset.
391 @retval EFI_SUCCESS The device was reset.
392 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
399 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
400 IN BOOLEAN ExtendedVerification
404 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
406 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
408 return ConsoleInDev
->ConIn
.Reset (
409 &ConsoleInDev
->ConIn
,
415 Reads the next keystroke from the input device. The WaitForKey Event can
416 be used to test for existance of a keystroke via WaitForEvent () call.
419 @param This Protocol instance pointer.
420 @param KeyData A pointer to a buffer that is filled in with the keystroke
421 state data for the key that was pressed.
423 @retval EFI_SUCCESS The keystroke information was returned.
424 @retval EFI_NOT_READY There was no keystroke data availiable.
425 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
427 @retval EFI_INVALID_PARAMETER KeyData is NULL.
432 KeyboardReadKeyStrokeEx (
433 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
434 OUT EFI_KEY_DATA
*KeyData
438 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
440 if (KeyData
== NULL
) {
441 return EFI_INVALID_PARAMETER
;
444 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
445 return KeyboardReadKeyStrokeWorker (ConsoleInDev
, KeyData
);
449 Set certain state for the input device.
451 @param This Protocol instance pointer.
452 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
453 state for the input device.
455 @retval EFI_SUCCESS The device state was set successfully.
456 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
457 not have the setting adjusted.
458 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
459 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
465 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
466 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
471 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
474 if (KeyToggleState
== NULL
) {
475 return EFI_INVALID_PARAMETER
;
478 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
481 // Enter critical section
483 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
485 if (ConsoleInDev
->KeyboardErr
) {
486 Status
= EFI_DEVICE_ERROR
;
490 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
491 Status
= EFI_UNSUPPORTED
;
496 // Update the status light
498 ConsoleInDev
->ScrollLock
= FALSE
;
499 ConsoleInDev
->NumLock
= FALSE
;
500 ConsoleInDev
->CapsLock
= FALSE
;
501 ConsoleInDev
->IsSupportPartialKey
= FALSE
;
503 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
504 ConsoleInDev
->ScrollLock
= TRUE
;
506 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
507 ConsoleInDev
->NumLock
= TRUE
;
509 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
510 ConsoleInDev
->CapsLock
= TRUE
;
512 if ((*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
) {
513 ConsoleInDev
->IsSupportPartialKey
= TRUE
;
516 Status
= UpdateStatusLights (ConsoleInDev
);
517 if (EFI_ERROR (Status
)) {
518 Status
= EFI_DEVICE_ERROR
;
523 // Leave critical section and return
525 gBS
->RestoreTPL (OldTpl
);
532 Register a notification function for a particular keystroke for the input device.
534 @param This Protocol instance pointer.
535 @param KeyData A pointer to a buffer that is filled in with the keystroke
536 information data for the key that was pressed.
537 @param KeyNotificationFunction Points to the function to be called when the key
538 sequence is typed specified by KeyData.
539 @param NotifyHandle Points to the unique handle assigned to the registered notification.
541 @retval EFI_SUCCESS The notification function was registered successfully.
542 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
543 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
548 KeyboardRegisterKeyNotify (
549 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
550 IN EFI_KEY_DATA
*KeyData
,
551 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
552 OUT VOID
**NotifyHandle
556 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
559 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
560 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
562 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
563 return EFI_INVALID_PARAMETER
;
566 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
569 // Enter critical section
571 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
574 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
576 for (Link
= ConsoleInDev
->NotifyList
.ForwardLink
; Link
!= &ConsoleInDev
->NotifyList
; Link
= Link
->ForwardLink
) {
579 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
581 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
583 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
584 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
585 *NotifyHandle
= CurrentNotify
;
586 Status
= EFI_SUCCESS
;
593 // Allocate resource to save the notification function
595 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
596 if (NewNotify
== NULL
) {
597 Status
= EFI_OUT_OF_RESOURCES
;
601 NewNotify
->Signature
= KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
602 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
603 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
604 InsertTailList (&ConsoleInDev
->NotifyList
, &NewNotify
->NotifyEntry
);
606 *NotifyHandle
= NewNotify
;
607 Status
= EFI_SUCCESS
;
611 // Leave critical section and return
613 gBS
->RestoreTPL (OldTpl
);
619 Remove a registered notification function from a particular keystroke.
621 @param This Protocol instance pointer.
622 @param NotificationHandle The handle of the notification function being unregistered.
625 @retval EFI_SUCCESS The notification function was unregistered successfully.
626 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
631 KeyboardUnregisterKeyNotify (
632 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
633 IN VOID
*NotificationHandle
637 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
640 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
642 if (NotificationHandle
== NULL
) {
643 return EFI_INVALID_PARAMETER
;
646 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
649 // Enter critical section
651 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
653 for (Link
= ConsoleInDev
->NotifyList
.ForwardLink
; Link
!= &ConsoleInDev
->NotifyList
; Link
= Link
->ForwardLink
) {
656 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
658 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
660 if (CurrentNotify
== NotificationHandle
) {
662 // Remove the notification function from NotifyList and free resources
664 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
666 gBS
->FreePool (CurrentNotify
);
667 Status
= EFI_SUCCESS
;
673 // Can not find the specified Notification Handle
675 Status
= EFI_INVALID_PARAMETER
;
678 // Leave critical section and return
680 gBS
->RestoreTPL (OldTpl
);