]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
17bbcc3136f6bb2d347be13c0bd235a34bc6f828
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdTextIn.c
1 /**@file
2 PS/2 Keyboard driver
3 Routines that support SIMPLE_TEXT_IN protocol
4
5 Copyright (c) 2006 - 2007, 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
10
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.
13
14 **/
15
16
17 #include "Ps2Keyboard.h"
18
19 //
20 // function declarations
21 //
22 EFI_STATUS
23 EFIAPI
24 KeyboardEfiReset (
25 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
26 IN BOOLEAN ExtendedVerification
27 );
28
29 EFI_STATUS
30 EFIAPI
31 KeyboardReadKeyStroke (
32 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
33 OUT EFI_INPUT_KEY *Key
34 );
35
36 VOID
37 EFIAPI
38 KeyboardWaitForKey (
39 IN EFI_EVENT Event,
40 IN VOID *Context
41 );
42
43 EFI_STATUS
44 KeyboardCheckForKey (
45 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
46 );
47
48 /**
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.
53
54 @retval TRUE - Key be pressed matches a registered key.
55 @retval FALSE - Match failed.
56
57 **/
58 STATIC
59 BOOLEAN
60 IsKeyRegistered (
61 IN EFI_KEY_DATA *RegsiteredData,
62 IN EFI_KEY_DATA *InputData
63 )
64 ;
65
66 /**
67 Reads the next keystroke from the input device. The WaitForKey Event can
68 be used to test for existance of a keystroke via WaitForEvent () call.
69
70
71 @param ConsoleInDev - Ps2 Keyboard private structure
72 @param KeyData - A pointer to a buffer that is filled in with the keystroke
73 state data for the key that was pressed.
74
75
76 @retval EFI_SUCCESS - The keystroke information was returned.
77 @retval EFI_NOT_READY - There was no keystroke data availiable.
78 @retval EFI_DEVICE_ERROR - The keystroke information was not returned due to
79 hardware errors.
80 @retval EFI_INVALID_PARAMETER - KeyData is NULL.
81
82 **/
83 STATIC
84 EFI_STATUS
85 KeyboardReadKeyStrokeWorker (
86 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev,
87 OUT EFI_KEY_DATA *KeyData
88 )
89
90 {
91 EFI_STATUS Status;
92 EFI_TPL OldTpl;
93 LIST_ENTRY *Link;
94 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
95 EFI_KEY_DATA OriginalKeyData;
96 if (KeyData == NULL) {
97 return EFI_INVALID_PARAMETER;
98 }
99
100 //
101 // Enter critical section
102 //
103 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
104
105 if (ConsoleInDev->KeyboardErr) {
106 gBS->RestoreTPL (OldTpl);
107 return EFI_DEVICE_ERROR;
108 }
109 //
110 // If there's no key, just return
111 //
112 Status = KeyboardCheckForKey (&ConsoleInDev->ConIn);
113 if (EFI_ERROR (Status)) {
114 gBS->RestoreTPL (OldTpl);
115 return EFI_NOT_READY;
116 }
117 CopyMem (&KeyData->Key, &ConsoleInDev->Key, sizeof (EFI_INPUT_KEY));
118
119 ConsoleInDev->Key.ScanCode = SCAN_NULL;
120 ConsoleInDev->Key.UnicodeChar = 0x0000;
121 CopyMem (&KeyData->KeyState, &ConsoleInDev->KeyState, sizeof (EFI_KEY_STATE));
122
123 ConsoleInDev->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
124 ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
125 gBS->RestoreTPL (OldTpl);
126 //
127 //Switch the control value to their original characters. In KeyGetchar() the CTRL-Alpha characters have been switched to
128 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.
129 //
130 CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));
131 if (ConsoleInDev->Ctrled) {
132 if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {
133 if (ConsoleInDev->CapsLock) {
134 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);
135 } else {
136 OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);
137 }
138 }
139 }
140 //
141 // Invoke notification functions if exist
142 //
143 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
144 CurrentNotify = CR (
145 Link,
146 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
147 NotifyEntry,
148 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
149 );
150 if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) {
151 CurrentNotify->KeyNotificationFn (&OriginalKeyData);
152 }
153 }
154
155 return EFI_SUCCESS;
156 }
157
158 /**
159 logic reset keyboard
160 Implement SIMPLE_TEXT_IN.Reset()
161 Perform 8042 controller and keyboard initialization
162
163 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
164 @param ExtendedVerification Indicate that the driver may perform a more
165 exhaustive verification operation of the device during
166 reset, now this par is ignored in this driver
167
168 **/
169 EFI_STATUS
170 EFIAPI
171 KeyboardEfiReset (
172 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
173 IN BOOLEAN ExtendedVerification
174 )
175 {
176 EFI_STATUS Status;
177 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
178 EFI_TPL OldTpl;
179
180 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
181 if (ConsoleIn->KeyboardErr) {
182 return EFI_DEVICE_ERROR;
183 }
184
185 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
186 EFI_PROGRESS_CODE,
187 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
188 ConsoleIn->DevicePath
189 );
190
191 //
192 // Enter critical section
193 //
194 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
195
196 //
197 // Call InitKeyboard to initialize the keyboard
198 //
199 Status = InitKeyboard (ConsoleIn, ExtendedVerification);
200 if (EFI_ERROR (Status)) {
201 //
202 // Leave critical section and return
203 //
204 gBS->RestoreTPL (OldTpl);
205 return EFI_DEVICE_ERROR;
206 }
207 //
208 // Clear the status of ConsoleIn.Key
209 //
210 ConsoleIn->Key.ScanCode = SCAN_NULL;
211 ConsoleIn->Key.UnicodeChar = 0x0000;
212
213 //
214 // Leave critical section and return
215 //
216 gBS->RestoreTPL (OldTpl);
217
218 //
219 // Report the status If a stuck key was detected
220 //
221 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
222 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
223 EFI_ERROR_CODE | EFI_ERROR_MINOR,
224 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY,
225 ConsoleIn->DevicePath
226 );
227 }
228 //
229 // Report the status If keyboard is locked
230 //
231 if (!(KeyReadStatusRegister (ConsoleIn) & 0x10)) {
232 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
233 EFI_ERROR_CODE | EFI_ERROR_MINOR,
234 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED,
235 ConsoleIn->DevicePath
236 );
237 }
238
239 return EFI_SUCCESS;
240 }
241
242 /**
243 Implement SIMPLE_TEXT_IN.ReadKeyStroke().
244 Retrieve key values for driver user.
245
246 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
247 @param Key The output buffer for key value
248
249 @retval EFI_SUCCESS success to read key stroke
250 **/
251 EFI_STATUS
252 EFIAPI
253 KeyboardReadKeyStroke (
254 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
255 OUT EFI_INPUT_KEY *Key
256 )
257 {
258 EFI_STATUS Status;
259 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
260 EFI_KEY_DATA KeyData;
261
262 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
263 Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);
264 if (EFI_ERROR (Status)) {
265 return Status;
266 }
267
268 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
269 return EFI_SUCCESS;
270
271 }
272
273 /**
274 Event notification function for SIMPLE_TEXT_IN.WaitForKey event
275 Signal the event if there is key available
276
277 @param Event the event object
278 @param Context waitting context
279
280 **/
281 VOID
282 EFIAPI
283 KeyboardWaitForKey (
284 IN EFI_EVENT Event,
285 IN VOID *Context
286 )
287 {
288 EFI_TPL OldTpl;
289 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
290
291 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context);
292
293 //
294 // Enter critical section
295 //
296 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
297
298 if (ConsoleIn->KeyboardErr) {
299 //
300 // Leave critical section and return
301 //
302 gBS->RestoreTPL (OldTpl);
303 return ;
304 }
305 //
306 // Someone is waiting on the keyboard event, if there's
307 // a key pending, signal the event
308 //
309 if (!EFI_ERROR (KeyboardCheckForKey (Context))) {
310 gBS->SignalEvent (Event);
311 }
312 //
313 // Leave critical section and return
314 //
315 gBS->RestoreTPL (OldTpl);
316
317 return ;
318 }
319
320 /**
321 Check keyboard for given key value
322
323 @param This Point to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
324
325 @retval EFI_SUCCESS success check keyboard value
326 **/
327 EFI_STATUS
328 KeyboardCheckForKey (
329 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
330 )
331 {
332 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
333
334 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
335
336 //
337 // If ready to read next key, check it
338 //
339 if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {
340 return KeyGetchar (ConsoleIn);
341 }
342
343 return EFI_SUCCESS;
344 }
345
346 /**
347 Judge whether is a registed key
348
349 @param RegsiteredData - A pointer to a buffer that is filled in with the keystroke
350 state data for the key that was registered.
351 @param InputData - A pointer to a buffer that is filled in with the keystroke
352 state data for the key that was pressed.
353
354 @retval TRUE - Key be pressed matches a registered key.
355 @retval FLASE - Match failed.
356
357 **/
358 STATIC
359 BOOLEAN
360 IsKeyRegistered (
361 IN EFI_KEY_DATA *RegsiteredData,
362 IN EFI_KEY_DATA *InputData
363 )
364
365 {
366 ASSERT (RegsiteredData != NULL && InputData != NULL);
367
368 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
369 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
370 return FALSE;
371 }
372
373 //
374 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
375 //
376 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
377 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
378 return FALSE;
379 }
380 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
381 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
382 return FALSE;
383 }
384
385 return TRUE;
386
387 }
388
389 /**
390 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
391 Signal the event if there is key available
392
393 @param Event event object
394 @param Context waiting context
395
396 **/
397 VOID
398 EFIAPI
399 KeyboardWaitForKeyEx (
400 IN EFI_EVENT Event,
401 IN VOID *Context
402 )
403
404 {
405 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
406
407 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context);
408 KeyboardWaitForKey (Event, &ConsoleInDev->ConIn);
409
410 }
411
412 /**
413 Reset the input device and optionaly run diagnostics
414
415 @param This - Protocol instance pointer.
416 @param ExtendedVerification - Driver may perform diagnostics on reset.
417
418 @retval EFI_SUCCESS - The device was reset.
419 @retval EFI_DEVICE_ERROR - The device is not functioning properly and could
420 not be reset.
421
422 **/
423 EFI_STATUS
424 EFIAPI
425 KeyboardEfiResetEx (
426 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
427 IN BOOLEAN ExtendedVerification
428 )
429
430 {
431 EFI_STATUS Status;
432 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
433 EFI_TPL OldTpl;
434
435 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
436 if (ConsoleInDev->KeyboardErr) {
437 return EFI_DEVICE_ERROR;
438 }
439
440 Status = ConsoleInDev->ConIn.Reset (
441 &ConsoleInDev->ConIn,
442 ExtendedVerification
443 );
444 if (EFI_ERROR (Status)) {
445 return EFI_DEVICE_ERROR;
446 }
447
448 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
449
450 ConsoleInDev->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
451 ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
452
453 gBS->RestoreTPL (OldTpl);
454
455 return EFI_SUCCESS;
456 }
457
458 /**
459 Reads the next keystroke from the input device. The WaitForKey Event can
460 be used to test for existance of a keystroke via WaitForEvent () call.
461
462
463 @param This - Protocol instance pointer.
464 @param KeyData - A pointer to a buffer that is filled in with the keystroke
465 state data for the key that was pressed.
466
467 @retval EFI_SUCCESS - The keystroke information was returned.
468 @retval EFI_NOT_READY - There was no keystroke data availiable.
469 @retval EFI_DEVICE_ERROR - The keystroke information was not returned due to
470 hardware errors.
471 @retval EFI_INVALID_PARAMETER - KeyData is NULL.
472
473 **/
474 EFI_STATUS
475 EFIAPI
476 KeyboardReadKeyStrokeEx (
477 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
478 OUT EFI_KEY_DATA *KeyData
479 )
480
481 {
482 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
483
484 if (KeyData == NULL) {
485 return EFI_INVALID_PARAMETER;
486 }
487
488 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
489 return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);
490
491 }
492
493 /**
494 Set certain state for the input device.
495
496 @param This - Protocol instance pointer.
497 @param KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
498 state for the input device.
499
500 @retval EFI_SUCCESS - The device state was set successfully.
501 @retval EFI_DEVICE_ERROR - The device is not functioning correctly and could
502 not have the setting adjusted.
503 @retval EFI_UNSUPPORTED - The device does not have the ability to set its state.
504 @retval EFI_INVALID_PARAMETER - KeyToggleState is NULL.
505
506 **/
507 EFI_STATUS
508 EFIAPI
509 KeyboardSetState (
510 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
511 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
512 )
513
514 {
515 EFI_STATUS Status;
516 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
517 EFI_TPL OldTpl;
518
519 if (KeyToggleState == NULL) {
520 return EFI_INVALID_PARAMETER;
521 }
522
523 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
524
525 //
526 // Enter critical section
527 //
528 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
529
530 if (ConsoleInDev->KeyboardErr) {
531 Status = EFI_DEVICE_ERROR;
532 goto Exit;
533 }
534
535 if (((ConsoleInDev->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||
536 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {
537 Status = EFI_UNSUPPORTED;
538 goto Exit;
539 }
540
541 //
542 // Update the status light
543 //
544 ConsoleInDev->ScrollLock = FALSE;
545 ConsoleInDev->NumLock = FALSE;
546 ConsoleInDev->CapsLock = FALSE;
547
548 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
549 ConsoleInDev->ScrollLock = TRUE;
550 }
551 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
552 ConsoleInDev->NumLock = TRUE;
553 }
554 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
555 ConsoleInDev->CapsLock = TRUE;
556 }
557
558 Status = UpdateStatusLights (ConsoleInDev);
559 if (EFI_ERROR (Status)) {
560 Status = EFI_DEVICE_ERROR;
561 }
562
563 ConsoleInDev->KeyState.KeyToggleState = *KeyToggleState;
564
565 Exit:
566 //
567 // Leave critical section and return
568 //
569 gBS->RestoreTPL (OldTpl);
570
571 return Status;
572
573 }
574
575 /**
576 Register a notification function for a particular keystroke for the input device.
577
578 @param This - Protocol instance pointer.
579 @param KeyData - A pointer to a buffer that is filled in with the keystroke
580 information data for the key that was pressed.
581 @param KeyNotificationFunction - Points to the function to be called when the key
582 sequence is typed specified by KeyData.
583 @param NotifyHandle - Points to the unique handle assigned to the registered notification.
584
585 @retval EFI_SUCCESS - The notification function was registered successfully.
586 @retval EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
587 @retval EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
588
589 **/
590 EFI_STATUS
591 EFIAPI
592 KeyboardRegisterKeyNotify (
593 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
594 IN EFI_KEY_DATA *KeyData,
595 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
596 OUT EFI_HANDLE *NotifyHandle
597 )
598 {
599 EFI_STATUS Status;
600 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
601 EFI_TPL OldTpl;
602 LIST_ENTRY *Link;
603 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
604 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
605
606 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
607 return EFI_INVALID_PARAMETER;
608 }
609
610 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
611
612 //
613 // Enter critical section
614 //
615 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
616
617 //
618 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
619 //
620 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
621 CurrentNotify = CR (
622 Link,
623 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
624 NotifyEntry,
625 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
626 );
627 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
628 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
629 *NotifyHandle = CurrentNotify->NotifyHandle;
630 Status = EFI_SUCCESS;
631 goto Exit;
632 }
633 }
634 }
635
636 //
637 // Allocate resource to save the notification function
638 //
639 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
640 if (NewNotify == NULL) {
641 Status = EFI_OUT_OF_RESOURCES;
642 goto Exit;
643 }
644
645 NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
646 NewNotify->KeyNotificationFn = KeyNotificationFunction;
647 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
648 InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);
649
650 //
651 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
652 //
653 Status = gBS->InstallMultipleProtocolInterfaces (
654 &NewNotify->NotifyHandle,
655 &gSimpleTextInExNotifyGuid,
656 NULL,
657 NULL
658 );
659 ASSERT_EFI_ERROR (Status);
660 *NotifyHandle = NewNotify->NotifyHandle;
661 Status = EFI_SUCCESS;
662
663 Exit:
664 //
665 // Leave critical section and return
666 //
667 gBS->RestoreTPL (OldTpl);
668 return Status;
669
670 }
671
672 /**
673 Remove a registered notification function from a particular keystroke.
674
675 @param This - Protocol instance pointer.
676 @param NotificationHandle - The handle of the notification function being unregistered.
677
678
679 @retval EFI_SUCCESS - The notification function was unregistered successfully.
680 @retval EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
681 @retval EFI_NOT_FOUND - Can not find the matching entry in database.
682
683 **/
684 EFI_STATUS
685 EFIAPI
686 KeyboardUnregisterKeyNotify (
687 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
688 IN EFI_HANDLE NotificationHandle
689 )
690 {
691 EFI_STATUS Status;
692 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
693 EFI_TPL OldTpl;
694 LIST_ENTRY *Link;
695 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
696
697 if (NotificationHandle == NULL) {
698 return EFI_INVALID_PARAMETER;
699 }
700
701 Status = gBS->OpenProtocol (
702 NotificationHandle,
703 &gSimpleTextInExNotifyGuid,
704 NULL,
705 NULL,
706 NULL,
707 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
708 );
709 if (EFI_ERROR (Status)) {
710 return EFI_INVALID_PARAMETER;
711 }
712
713 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
714
715 //
716 // Enter critical section
717 //
718 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
719
720 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
721 CurrentNotify = CR (
722 Link,
723 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
724 NotifyEntry,
725 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
726 );
727 if (CurrentNotify->NotifyHandle == NotificationHandle) {
728 //
729 // Remove the notification function from NotifyList and free resources
730 //
731 RemoveEntryList (&CurrentNotify->NotifyEntry);
732 Status = gBS->UninstallMultipleProtocolInterfaces (
733 CurrentNotify->NotifyHandle,
734 &gSimpleTextInExNotifyGuid,
735 NULL,
736 NULL
737 );
738 ASSERT_EFI_ERROR (Status);
739 gBS->FreePool (CurrentNotify);
740 Status = EFI_SUCCESS;
741 goto Exit;
742 }
743 }
744
745 //
746 // Can not find the specified Notification Handle
747 //
748 Status = EFI_NOT_FOUND;
749 Exit:
750 //
751 // Leave critical section and return
752 //
753 gBS->RestoreTPL (OldTpl);
754 return Status;
755 }
756