2 Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
3 provided by Ps2KbdCtrller.c.
5 Copyright (c) 2006 - 2011, 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
);
38 Push one key data to the EFI key buffer.
40 @param Queue Pointer to instance of EFI_KEY_QUEUE.
41 @param KeyData The key data to push.
45 IN EFI_KEY_QUEUE
*Queue
,
46 IN EFI_KEY_DATA
*KeyData
49 if ((Queue
->Tail
+ 1) % KEYBOARD_EFI_KEY_MAX_COUNT
== Queue
->Head
) {
53 CopyMem (&Queue
->Buffer
[Queue
->Tail
], KeyData
, sizeof (EFI_KEY_DATA
));
54 Queue
->Tail
= (Queue
->Tail
+ 1) % KEYBOARD_EFI_KEY_MAX_COUNT
;
58 Read & remove one key data from the EFI key buffer.
60 @param Queue Pointer to instance of EFI_KEY_QUEUE.
61 @param KeyData Receive the key data.
63 @retval EFI_SUCCESS The key data is popped successfully.
64 @retval EFI_NOT_READY There is no key data available.
68 IN EFI_KEY_QUEUE
*Queue
,
69 OUT EFI_KEY_DATA
*KeyData
72 if (IsEfikeyBufEmpty (Queue
)) {
76 // Retrieve and remove the values
78 CopyMem (KeyData
, &Queue
->Buffer
[Queue
->Head
], sizeof (EFI_KEY_DATA
));
79 Queue
->Head
= (Queue
->Head
+ 1) % KEYBOARD_EFI_KEY_MAX_COUNT
;
84 Judge whether is a registed key
86 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
87 state data for the key that was registered.
88 @param InputData A pointer to a buffer that is filled in with the keystroke
89 state data for the key that was pressed.
91 @retval TRUE Key be pressed matches a registered key.
92 @retval FLASE Match failed.
97 IN EFI_KEY_DATA
*RegsiteredData
,
98 IN EFI_KEY_DATA
*InputData
102 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
104 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
105 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
110 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
112 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
113 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
116 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
117 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
126 Reads the next keystroke from the input device. The WaitForKey Event can
127 be used to test for existance of a keystroke via WaitForEvent () call.
129 @param ConsoleInDev Ps2 Keyboard private structure
130 @param KeyData A pointer to a buffer that is filled in with the keystroke
131 state data for the key that was pressed.
134 @retval EFI_SUCCESS The keystroke information was returned.
135 @retval EFI_NOT_READY There was no keystroke data availiable.
136 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
138 @retval EFI_INVALID_PARAMETER KeyData is NULL.
142 KeyboardReadKeyStrokeWorker (
143 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
,
144 OUT EFI_KEY_DATA
*KeyData
151 if (KeyData
== NULL
) {
152 return EFI_INVALID_PARAMETER
;
156 // Enter critical section
158 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
160 KeyboardTimerHandler (NULL
, ConsoleInDev
);
162 if (ConsoleInDev
->KeyboardErr
) {
163 Status
= EFI_DEVICE_ERROR
;
165 Status
= PopEfikeyBufHead (&ConsoleInDev
->EfiKeyQueue
, KeyData
);
168 gBS
->RestoreTPL (OldTpl
);
173 Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()
175 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
176 @param ExtendedVerification Indicate that the driver may perform a more
177 exhaustive verification operation of the device during
178 reset, now this par is ignored in this driver
184 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
185 IN BOOLEAN ExtendedVerification
189 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
192 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
193 if (ConsoleIn
->KeyboardErr
) {
194 return EFI_DEVICE_ERROR
;
197 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
199 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
,
200 ConsoleIn
->DevicePath
204 // Enter critical section
206 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
209 // Call InitKeyboard to initialize the keyboard
211 Status
= InitKeyboard (ConsoleIn
, ExtendedVerification
);
212 if (EFI_ERROR (Status
)) {
214 // Leave critical section and return
216 gBS
->RestoreTPL (OldTpl
);
217 return EFI_DEVICE_ERROR
;
221 // Leave critical section and return
223 gBS
->RestoreTPL (OldTpl
);
226 // Report the status If a stuck key was detected
228 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
229 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
230 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
231 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_EC_STUCK_KEY
,
232 ConsoleIn
->DevicePath
236 // Report the status If keyboard is locked
238 if ((KeyReadStatusRegister (ConsoleIn
) & 0x10) == 0) {
239 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
240 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
241 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_EC_LOCKED
,
242 ConsoleIn
->DevicePath
250 Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().
252 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
253 @param Key The output buffer for key value
255 @retval EFI_SUCCESS success to read key stroke
259 KeyboardReadKeyStroke (
260 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
261 OUT EFI_INPUT_KEY
*Key
265 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
266 EFI_KEY_DATA KeyData
;
268 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
269 Status
= KeyboardReadKeyStrokeWorker (ConsoleIn
, &KeyData
);
270 if (EFI_ERROR (Status
)) {
274 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
280 Event notification function for SIMPLE_TEXT_IN.WaitForKey event
281 Signal the event if there is key available
283 @param Event the event object
284 @param Context waitting context
295 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
297 ConsoleIn
= (KEYBOARD_CONSOLE_IN_DEV
*) Context
;
300 // Enter critical section
302 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
304 KeyboardTimerHandler (NULL
, ConsoleIn
);
306 if (!ConsoleIn
->KeyboardErr
) {
308 // Someone is waiting on the keyboard event, if there's
309 // a key pending, signal the event
311 if (!IsEfikeyBufEmpty (&ConsoleIn
->EfiKeyQueue
)) {
312 gBS
->SignalEvent (Event
);
316 // Leave critical section and return
318 gBS
->RestoreTPL (OldTpl
);
322 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
323 Signal the event if there is key available
325 @param Event event object
326 @param Context waiting context
331 KeyboardWaitForKeyEx (
337 KeyboardWaitForKey (Event
, Context
);
341 Reset the input device and optionaly run diagnostics
343 @param This Protocol instance pointer.
344 @param ExtendedVerification Driver may perform diagnostics on reset.
346 @retval EFI_SUCCESS The device was reset.
347 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
354 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
355 IN BOOLEAN ExtendedVerification
359 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
361 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
363 return ConsoleInDev
->ConIn
.Reset (
364 &ConsoleInDev
->ConIn
,
370 Reads the next keystroke from the input device. The WaitForKey Event can
371 be used to test for existance of a keystroke via WaitForEvent () call.
374 @param This Protocol instance pointer.
375 @param KeyData A pointer to a buffer that is filled in with the keystroke
376 state data for the key that was pressed.
378 @retval EFI_SUCCESS The keystroke information was returned.
379 @retval EFI_NOT_READY There was no keystroke data availiable.
380 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
382 @retval EFI_INVALID_PARAMETER KeyData is NULL.
387 KeyboardReadKeyStrokeEx (
388 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
389 OUT EFI_KEY_DATA
*KeyData
393 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
395 if (KeyData
== NULL
) {
396 return EFI_INVALID_PARAMETER
;
399 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
400 return KeyboardReadKeyStrokeWorker (ConsoleInDev
, KeyData
);
405 Set certain state for the input device.
407 @param This Protocol instance pointer.
408 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
409 state for the input device.
411 @retval EFI_SUCCESS The device state was set successfully.
412 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
413 not have the setting adjusted.
414 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
415 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
421 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
422 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
427 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
430 if (KeyToggleState
== NULL
) {
431 return EFI_INVALID_PARAMETER
;
434 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
437 // Enter critical section
439 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
441 if (ConsoleInDev
->KeyboardErr
) {
442 Status
= EFI_DEVICE_ERROR
;
446 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
447 Status
= EFI_UNSUPPORTED
;
452 // Update the status light
454 ConsoleInDev
->ScrollLock
= FALSE
;
455 ConsoleInDev
->NumLock
= FALSE
;
456 ConsoleInDev
->CapsLock
= FALSE
;
458 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
459 ConsoleInDev
->ScrollLock
= TRUE
;
461 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
462 ConsoleInDev
->NumLock
= TRUE
;
464 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
465 ConsoleInDev
->CapsLock
= TRUE
;
468 Status
= UpdateStatusLights (ConsoleInDev
);
469 if (EFI_ERROR (Status
)) {
470 Status
= EFI_DEVICE_ERROR
;
475 // Leave critical section and return
477 gBS
->RestoreTPL (OldTpl
);
484 Register a notification function for a particular keystroke for the input device.
486 @param This Protocol instance pointer.
487 @param KeyData A pointer to a buffer that is filled in with the keystroke
488 information data for the key that was pressed.
489 @param KeyNotificationFunction Points to the function to be called when the key
490 sequence is typed specified by KeyData.
491 @param NotifyHandle Points to the unique handle assigned to the registered notification.
493 @retval EFI_SUCCESS The notification function was registered successfully.
494 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
495 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
500 KeyboardRegisterKeyNotify (
501 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
502 IN EFI_KEY_DATA
*KeyData
,
503 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
504 OUT EFI_HANDLE
*NotifyHandle
508 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
511 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
512 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
514 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
515 return EFI_INVALID_PARAMETER
;
518 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
521 // Enter critical section
523 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
526 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
528 for (Link
= ConsoleInDev
->NotifyList
.ForwardLink
; Link
!= &ConsoleInDev
->NotifyList
; Link
= Link
->ForwardLink
) {
531 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
533 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
535 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
536 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
537 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
538 Status
= EFI_SUCCESS
;
545 // Allocate resource to save the notification function
547 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
548 if (NewNotify
== NULL
) {
549 Status
= EFI_OUT_OF_RESOURCES
;
553 NewNotify
->Signature
= KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
554 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
555 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
556 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
557 InsertTailList (&ConsoleInDev
->NotifyList
, &NewNotify
->NotifyEntry
);
559 *NotifyHandle
= NewNotify
->NotifyHandle
;
560 Status
= EFI_SUCCESS
;
564 // Leave critical section and return
566 gBS
->RestoreTPL (OldTpl
);
572 Remove a registered notification function from a particular keystroke.
574 @param This Protocol instance pointer.
575 @param NotificationHandle The handle of the notification function being unregistered.
578 @retval EFI_SUCCESS The notification function was unregistered successfully.
579 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
584 KeyboardUnregisterKeyNotify (
585 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
586 IN EFI_HANDLE NotificationHandle
590 KEYBOARD_CONSOLE_IN_DEV
*ConsoleInDev
;
593 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
595 if (NotificationHandle
== NULL
) {
596 return EFI_INVALID_PARAMETER
;
599 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
600 return EFI_INVALID_PARAMETER
;
603 ConsoleInDev
= TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This
);
606 // Enter critical section
608 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
610 for (Link
= ConsoleInDev
->NotifyList
.ForwardLink
; Link
!= &ConsoleInDev
->NotifyList
; Link
= Link
->ForwardLink
) {
613 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
615 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
617 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
619 // Remove the notification function from NotifyList and free resources
621 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
623 gBS
->FreePool (CurrentNotify
);
624 Status
= EFI_SUCCESS
;
630 // Can not find the specified Notification Handle
632 Status
= EFI_INVALID_PARAMETER
;
635 // Leave critical section and return
637 gBS
->RestoreTPL (OldTpl
);