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