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