]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
76779553cd38a0a762bf4c530fb27c392899089c
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdTextIn.c
1 /** @file
2 Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
3 provided by Ps2KbdCtrller.c.
4
5 Copyright (c) 2006 - 2017, 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
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 Check whether the EFI key buffer is empty.
21
22 @param Queue Pointer to instance of EFI_KEY_QUEUE.
23
24 @retval TRUE The EFI key buffer is empty.
25 @retval FALSE The EFI key buffer isn't empty.
26 **/
27 BOOLEAN
28 IsEfikeyBufEmpty (
29 IN EFI_KEY_QUEUE *Queue
30 )
31 {
32 return (BOOLEAN) (Queue->Head == Queue->Tail);
33 }
34
35 /**
36 Read & remove one key data from the EFI key buffer.
37
38 @param Queue Pointer to instance of EFI_KEY_QUEUE.
39 @param KeyData Receive the key data.
40
41 @retval EFI_SUCCESS The key data is popped successfully.
42 @retval EFI_NOT_READY There is no key data available.
43 **/
44 EFI_STATUS
45 PopEfikeyBufHead (
46 IN EFI_KEY_QUEUE *Queue,
47 OUT EFI_KEY_DATA *KeyData OPTIONAL
48 )
49 {
50 if (IsEfikeyBufEmpty (Queue)) {
51 return EFI_NOT_READY;
52 }
53 //
54 // Retrieve and remove the values
55 //
56 if (KeyData != NULL) {
57 CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));
58 }
59 Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
60 return EFI_SUCCESS;
61 }
62
63 /**
64 Push one key data to the EFI key buffer.
65
66 @param Queue Pointer to instance of EFI_KEY_QUEUE.
67 @param KeyData The key data to push.
68 **/
69 VOID
70 PushEfikeyBufTail (
71 IN EFI_KEY_QUEUE *Queue,
72 IN EFI_KEY_DATA *KeyData
73 )
74 {
75 if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {
76 //
77 // If Queue is full, pop the one from head.
78 //
79 PopEfikeyBufHead (Queue, NULL);
80 }
81 CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));
82 Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
83 }
84
85 /**
86 Judge whether is a registed key
87
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.
92
93 @retval TRUE Key be pressed matches a registered key.
94 @retval FLASE Match failed.
95
96 **/
97 BOOLEAN
98 IsKeyRegistered (
99 IN EFI_KEY_DATA *RegsiteredData,
100 IN EFI_KEY_DATA *InputData
101 )
102
103 {
104 ASSERT (RegsiteredData != NULL && InputData != NULL);
105
106 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
107 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
108 return FALSE;
109 }
110
111 //
112 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
113 //
114 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
115 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
116 return FALSE;
117 }
118 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
119 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
120 return FALSE;
121 }
122
123 return TRUE;
124
125 }
126
127 /**
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.
130
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.
134
135
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
139 hardware errors.
140 @retval EFI_INVALID_PARAMETER KeyData is NULL.
141
142 **/
143 EFI_STATUS
144 KeyboardReadKeyStrokeWorker (
145 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev,
146 OUT EFI_KEY_DATA *KeyData
147 )
148
149 {
150 EFI_STATUS Status;
151 EFI_TPL OldTpl;
152
153 if (KeyData == NULL) {
154 return EFI_INVALID_PARAMETER;
155 }
156
157 //
158 // Enter critical section
159 //
160 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
161
162 KeyboardTimerHandler (NULL, ConsoleInDev);
163
164 if (ConsoleInDev->KeyboardErr) {
165 Status = EFI_DEVICE_ERROR;
166 } else {
167 Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);
168 }
169
170 gBS->RestoreTPL (OldTpl);
171 return Status;
172 }
173
174 /**
175 Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()
176
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
181
182 **/
183 EFI_STATUS
184 EFIAPI
185 KeyboardEfiReset (
186 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
187 IN BOOLEAN ExtendedVerification
188 )
189 {
190 EFI_STATUS Status;
191 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
192 EFI_TPL OldTpl;
193
194 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
195 if (ConsoleIn->KeyboardErr) {
196 return EFI_DEVICE_ERROR;
197 }
198
199 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
200 EFI_PROGRESS_CODE,
201 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
202 ConsoleIn->DevicePath
203 );
204
205 //
206 // Enter critical section
207 //
208 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
209
210 //
211 // Call InitKeyboard to initialize the keyboard
212 //
213 Status = InitKeyboard (ConsoleIn, ExtendedVerification);
214 if (EFI_ERROR (Status)) {
215 //
216 // Leave critical section and return
217 //
218 gBS->RestoreTPL (OldTpl);
219 return EFI_DEVICE_ERROR;
220 }
221
222 //
223 // Leave critical section and return
224 //
225 gBS->RestoreTPL (OldTpl);
226
227 //
228 // Report the status If a stuck key was detected
229 //
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
235 );
236 }
237 //
238 // Report the status If keyboard is locked
239 //
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
245 );
246 }
247
248 return EFI_SUCCESS;
249 }
250
251 /**
252 Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().
253
254 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
255 @param Key The output buffer for key value
256
257 @retval EFI_SUCCESS success to read key stroke
258 **/
259 EFI_STATUS
260 EFIAPI
261 KeyboardReadKeyStroke (
262 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
263 OUT EFI_INPUT_KEY *Key
264 )
265 {
266 EFI_STATUS Status;
267 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
268 EFI_KEY_DATA KeyData;
269
270 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
271
272 //
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
276 //
277 while (1) {
278 //
279 // If there is no pending key, then return.
280 //
281 Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);
282 if (EFI_ERROR (Status)) {
283 return Status;
284 }
285 //
286 // If it is partial keystroke, skip it.
287 //
288 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
289 continue;
290 }
291 //
292 // Translate the CTRL-Alpha characters to their corresponding control value
293 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
294 //
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);
300 }
301 }
302
303 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
304 return EFI_SUCCESS;
305 }
306 }
307
308 /**
309 Event notification function for SIMPLE_TEXT_IN.WaitForKey event
310 Signal the event if there is key available
311
312 @param Event the event object
313 @param Context waitting context
314
315 **/
316 VOID
317 EFIAPI
318 KeyboardWaitForKey (
319 IN EFI_EVENT Event,
320 IN VOID *Context
321 )
322 {
323 EFI_TPL OldTpl;
324 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
325 EFI_KEY_DATA KeyData;
326
327 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
328
329 //
330 // Enter critical section
331 //
332 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
333
334 KeyboardTimerHandler (NULL, ConsoleIn);
335
336 if (!ConsoleIn->KeyboardErr) {
337 //
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
342 //
343 while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {
344 CopyMem (
345 &KeyData,
346 &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]),
347 sizeof (EFI_KEY_DATA)
348 );
349 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
350 PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData);
351 continue;
352 }
353 //
354 // if there is pending value key, signal the event.
355 //
356 gBS->SignalEvent (Event);
357 break;
358 }
359 }
360 //
361 // Leave critical section and return
362 //
363 gBS->RestoreTPL (OldTpl);
364 }
365
366 /**
367 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
368 Signal the event if there is key available
369
370 @param Event event object
371 @param Context waiting context
372
373 **/
374 VOID
375 EFIAPI
376 KeyboardWaitForKeyEx (
377 IN EFI_EVENT Event,
378 IN VOID *Context
379 )
380
381 {
382 KeyboardWaitForKey (Event, Context);
383 }
384
385 /**
386 Reset the input device and optionaly run diagnostics
387
388 @param This Protocol instance pointer.
389 @param ExtendedVerification Driver may perform diagnostics on reset.
390
391 @retval EFI_SUCCESS The device was reset.
392 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
393 not be reset.
394
395 **/
396 EFI_STATUS
397 EFIAPI
398 KeyboardEfiResetEx (
399 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
400 IN BOOLEAN ExtendedVerification
401 )
402
403 {
404 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
405
406 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
407
408 return ConsoleInDev->ConIn.Reset (
409 &ConsoleInDev->ConIn,
410 ExtendedVerification
411 );
412 }
413
414 /**
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.
417
418
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.
422
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
426 hardware errors.
427 @retval EFI_INVALID_PARAMETER KeyData is NULL.
428
429 **/
430 EFI_STATUS
431 EFIAPI
432 KeyboardReadKeyStrokeEx (
433 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
434 OUT EFI_KEY_DATA *KeyData
435 )
436
437 {
438 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
439
440 if (KeyData == NULL) {
441 return EFI_INVALID_PARAMETER;
442 }
443
444 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
445 return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);
446 }
447
448 /**
449 Set certain state for the input device.
450
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.
454
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.
460
461 **/
462 EFI_STATUS
463 EFIAPI
464 KeyboardSetState (
465 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
466 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
467 )
468
469 {
470 EFI_STATUS Status;
471 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
472 EFI_TPL OldTpl;
473
474 if (KeyToggleState == NULL) {
475 return EFI_INVALID_PARAMETER;
476 }
477
478 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
479
480 //
481 // Enter critical section
482 //
483 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
484
485 if (ConsoleInDev->KeyboardErr) {
486 Status = EFI_DEVICE_ERROR;
487 goto Exit;
488 }
489
490 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
491 Status = EFI_UNSUPPORTED;
492 goto Exit;
493 }
494
495 //
496 // Update the status light
497 //
498 ConsoleInDev->ScrollLock = FALSE;
499 ConsoleInDev->NumLock = FALSE;
500 ConsoleInDev->CapsLock = FALSE;
501 ConsoleInDev->IsSupportPartialKey = FALSE;
502
503 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
504 ConsoleInDev->ScrollLock = TRUE;
505 }
506 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
507 ConsoleInDev->NumLock = TRUE;
508 }
509 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
510 ConsoleInDev->CapsLock = TRUE;
511 }
512 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {
513 ConsoleInDev->IsSupportPartialKey = TRUE;
514 }
515
516 Status = UpdateStatusLights (ConsoleInDev);
517 if (EFI_ERROR (Status)) {
518 Status = EFI_DEVICE_ERROR;
519 }
520
521 Exit:
522 //
523 // Leave critical section and return
524 //
525 gBS->RestoreTPL (OldTpl);
526
527 return Status;
528
529 }
530
531 /**
532 Register a notification function for a particular keystroke for the input device.
533
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. If KeyData.Key,
537 KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState
538 are 0, then any incomplete keystroke will trigger a notification of
539 the KeyNotificationFunction.
540 @param KeyNotificationFunction Points to the function to be called when the key
541 sequence is typed specified by KeyData. This notification function
542 should be called at <=TPL_CALLBACK.
543 @param NotifyHandle Points to the unique handle assigned to the registered notification.
544
545 @retval EFI_SUCCESS The notification function was registered successfully.
546 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
547 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
548
549 **/
550 EFI_STATUS
551 EFIAPI
552 KeyboardRegisterKeyNotify (
553 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
554 IN EFI_KEY_DATA *KeyData,
555 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
556 OUT VOID **NotifyHandle
557 )
558 {
559 EFI_STATUS Status;
560 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
561 EFI_TPL OldTpl;
562 LIST_ENTRY *Link;
563 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
564 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
565
566 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
567 return EFI_INVALID_PARAMETER;
568 }
569
570 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
571
572 //
573 // Enter critical section
574 //
575 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
576
577 //
578 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
579 //
580 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
581 CurrentNotify = CR (
582 Link,
583 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
584 NotifyEntry,
585 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
586 );
587 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
588 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
589 *NotifyHandle = CurrentNotify;
590 Status = EFI_SUCCESS;
591 goto Exit;
592 }
593 }
594 }
595
596 //
597 // Allocate resource to save the notification function
598 //
599 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
600 if (NewNotify == NULL) {
601 Status = EFI_OUT_OF_RESOURCES;
602 goto Exit;
603 }
604
605 NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
606 NewNotify->KeyNotificationFn = KeyNotificationFunction;
607 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
608 InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);
609
610 *NotifyHandle = NewNotify;
611 Status = EFI_SUCCESS;
612
613 Exit:
614 //
615 // Leave critical section and return
616 //
617 gBS->RestoreTPL (OldTpl);
618 return Status;
619
620 }
621
622 /**
623 Remove a registered notification function from a particular keystroke.
624
625 @param This Protocol instance pointer.
626 @param NotificationHandle The handle of the notification function being unregistered.
627
628
629 @retval EFI_SUCCESS The notification function was unregistered successfully.
630 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
631
632 **/
633 EFI_STATUS
634 EFIAPI
635 KeyboardUnregisterKeyNotify (
636 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
637 IN VOID *NotificationHandle
638 )
639 {
640 EFI_STATUS Status;
641 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
642 EFI_TPL OldTpl;
643 LIST_ENTRY *Link;
644 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
645
646 if (NotificationHandle == NULL) {
647 return EFI_INVALID_PARAMETER;
648 }
649
650 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
651
652 //
653 // Enter critical section
654 //
655 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
656
657 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
658 CurrentNotify = CR (
659 Link,
660 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
661 NotifyEntry,
662 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
663 );
664 if (CurrentNotify == NotificationHandle) {
665 //
666 // Remove the notification function from NotifyList and free resources
667 //
668 RemoveEntryList (&CurrentNotify->NotifyEntry);
669
670 gBS->FreePool (CurrentNotify);
671 Status = EFI_SUCCESS;
672 goto Exit;
673 }
674 }
675
676 //
677 // Can not find the specified Notification Handle
678 //
679 Status = EFI_INVALID_PARAMETER;
680 Exit:
681 //
682 // Leave critical section and return
683 //
684 gBS->RestoreTPL (OldTpl);
685 return Status;
686 }
687
688 /**
689 Process key notify.
690
691 @param Event Indicates the event that invoke this function.
692 @param Context Indicates the calling context.
693 **/
694 VOID
695 EFIAPI
696 KeyNotifyProcessHandler (
697 IN EFI_EVENT Event,
698 IN VOID *Context
699 )
700 {
701 EFI_STATUS Status;
702 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
703 EFI_KEY_DATA KeyData;
704 LIST_ENTRY *Link;
705 LIST_ENTRY *NotifyList;
706 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
707 EFI_TPL OldTpl;
708
709 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
710
711 //
712 // Invoke notification functions.
713 //
714 NotifyList = &ConsoleIn->NotifyList;
715 while (TRUE) {
716 //
717 // Enter critical section
718 //
719 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
720 Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);
721 //
722 // Leave critical section
723 //
724 gBS->RestoreTPL (OldTpl);
725 if (EFI_ERROR (Status)) {
726 break;
727 }
728 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
729 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
730 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
731 CurrentNotify->KeyNotificationFn (&KeyData);
732 }
733 }
734 }
735 }
736