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