]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
Fix the PS2 keyboard driver to call hotkey callback even no one is calling ReadKeyStroke
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdTextIn.c
CommitLineData
f713c4fe 1/** @file\r
b6763e03 2 Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces\r
3 provided by Ps2KbdCtrller.c.\r
05fbd06d 4\r
c220787b 5Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
180a5a35 6This program and the accompanying materials\r
df0dcb5e 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
b6763e03 19/**\r
c220787b
RN
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\r
37/**\r
38 Push one key data to the EFI key buffer.\r
39\r
40 @param Queue Pointer to instance of EFI_KEY_QUEUE.\r
41 @param KeyData The key data to push.\r
42**/\r
43VOID\r
44PushEfikeyBufTail (\r
45 IN EFI_KEY_QUEUE *Queue,\r
46 IN EFI_KEY_DATA *KeyData\r
47 )\r
48{\r
49 if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {\r
50 return;\r
51 }\r
b6763e03 52 \r
c220787b
RN
53 CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));\r
54 Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;\r
55}\r
56\r
57/**\r
58 Read & remove one key data from the EFI key buffer.\r
b6763e03 59 \r
c220787b
RN
60 @param Queue Pointer to instance of EFI_KEY_QUEUE.\r
61 @param KeyData Receive the key data.\r
62\r
63 @retval EFI_SUCCESS The key data is popped successfully.\r
64 @retval EFI_NOT_READY There is no key data available.\r
b6763e03 65**/\r
05fbd06d 66EFI_STATUS\r
c220787b
RN
67PopEfikeyBufHead (\r
68 IN EFI_KEY_QUEUE *Queue,\r
69 OUT EFI_KEY_DATA *KeyData\r
b6763e03 70 )\r
71{\r
c220787b
RN
72 if (IsEfikeyBufEmpty (Queue)) {\r
73 return EFI_NOT_READY;\r
74 }\r
b6763e03 75 //\r
c220787b 76 // Retrieve and remove the values\r
b6763e03 77 //\r
c220787b
RN
78 CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));\r
79 Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;\r
b6763e03 80 return EFI_SUCCESS;\r
81}\r
05fbd06d 82\r
bcd70414 83/**\r
b6763e03 84 Judge whether is a registed key\r
85\r
86 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke \r
87 state data for the key that was registered.\r
88 @param InputData A pointer to a buffer that is filled in with the keystroke \r
89 state data for the key that was pressed.\r
bcd70414 90\r
b6763e03 91 @retval TRUE Key be pressed matches a registered key.\r
92 @retval FLASE Match failed. \r
bcd70414 93 \r
94**/\r
f3d1e940 95BOOLEAN\r
96IsKeyRegistered (\r
97 IN EFI_KEY_DATA *RegsiteredData,\r
98 IN EFI_KEY_DATA *InputData\r
b6763e03 99 )\r
100\r
101{\r
102 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
103 \r
104 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
105 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
106 return FALSE; \r
107 } \r
108 \r
109 //\r
110 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
111 //\r
112 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
113 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
114 return FALSE; \r
115 } \r
116 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
117 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
118 return FALSE; \r
119 } \r
120 \r
121 return TRUE;\r
122\r
123}\r
f3d1e940 124\r
bcd70414 125/**\r
126 Reads the next keystroke from the input device. The WaitForKey Event can \r
127 be used to test for existance of a keystroke via WaitForEvent () call.\r
bcd70414 128 \r
b6763e03 129 @param ConsoleInDev Ps2 Keyboard private structure\r
130 @param KeyData A pointer to a buffer that is filled in with the keystroke \r
131 state data for the key that was pressed.\r
f3d1e940 132\r
f3d1e940 133 \r
b6763e03 134 @retval EFI_SUCCESS The keystroke information was returned.\r
135 @retval EFI_NOT_READY There was no keystroke data availiable.\r
136 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to \r
137 hardware errors.\r
138 @retval EFI_INVALID_PARAMETER KeyData is NULL. \r
bcd70414 139\r
140**/\r
f3d1e940 141EFI_STATUS\r
142KeyboardReadKeyStrokeWorker (\r
143 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev,\r
144 OUT EFI_KEY_DATA *KeyData\r
145 )\r
f3d1e940 146\r
f3d1e940 147{\r
148 EFI_STATUS Status;\r
149 EFI_TPL OldTpl;\r
b6763e03 150 \r
f3d1e940 151 if (KeyData == NULL) {\r
152 return EFI_INVALID_PARAMETER;\r
153 }\r
154 \r
155 //\r
156 // Enter critical section\r
157 //\r
158 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
159\r
c220787b 160 KeyboardTimerHandler (NULL, ConsoleInDev);\r
b6763e03 161 \r
c220787b
RN
162 if (ConsoleInDev->KeyboardErr) {\r
163 Status = EFI_DEVICE_ERROR;\r
164 } else {\r
165 Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);\r
f3d1e940 166 }\r
167\r
c220787b
RN
168 gBS->RestoreTPL (OldTpl);\r
169 return Status;\r
f3d1e940 170}\r
171\r
bcd70414 172/**\r
b6763e03 173 Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()\r
bcd70414 174\r
b6763e03 175 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
bcd70414 176 @param ExtendedVerification Indicate that the driver may perform a more \r
177 exhaustive verification operation of the device during \r
178 reset, now this par is ignored in this driver \r
179\r
180**/\r
05fbd06d 181EFI_STATUS\r
182EFIAPI\r
183KeyboardEfiReset (\r
184 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
185 IN BOOLEAN ExtendedVerification\r
186 )\r
05fbd06d 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
05fbd06d 219\r
220 //\r
221 // Leave critical section and return\r
222 //\r
223 gBS->RestoreTPL (OldTpl);\r
224\r
225 //\r
226 // Report the status If a stuck key was detected\r
227 //\r
228 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {\r
229 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
230 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
231 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY,\r
232 ConsoleIn->DevicePath\r
233 );\r
234 }\r
235 //\r
236 // Report the status If keyboard is locked\r
237 //\r
f713c4fe 238 if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) {\r
05fbd06d 239 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
240 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
241 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED,\r
242 ConsoleIn->DevicePath\r
243 );\r
244 }\r
245\r
246 return EFI_SUCCESS;\r
247}\r
248\r
bcd70414 249/**\r
b6763e03 250 Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().\r
bcd70414 251\r
252 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
253 @param Key The output buffer for key value \r
254\r
255 @retval EFI_SUCCESS success to read key stroke\r
256**/\r
05fbd06d 257EFI_STATUS\r
258EFIAPI\r
259KeyboardReadKeyStroke (\r
260 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
261 OUT EFI_INPUT_KEY *Key\r
262 )\r
05fbd06d 263{\r
264 EFI_STATUS Status;\r
265 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
f3d1e940 266 EFI_KEY_DATA KeyData;\r
05fbd06d 267\r
268 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
f3d1e940 269 Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);\r
05fbd06d 270 if (EFI_ERROR (Status)) {\r
f3d1e940 271 return Status;\r
05fbd06d 272 }\r
273\r
f3d1e940 274 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
05fbd06d 275 return EFI_SUCCESS;\r
f3d1e940 276 \r
05fbd06d 277}\r
278\r
bcd70414 279/**\r
280 Event notification function for SIMPLE_TEXT_IN.WaitForKey event\r
281 Signal the event if there is key available\r
282\r
283 @param Event the event object\r
284 @param Context waitting context\r
285\r
286**/\r
05fbd06d 287VOID\r
288EFIAPI\r
289KeyboardWaitForKey (\r
290 IN EFI_EVENT Event,\r
291 IN VOID *Context\r
292 )\r
05fbd06d 293{\r
c220787b
RN
294 EFI_TPL OldTpl;\r
295 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
05fbd06d 296\r
c220787b 297 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
05fbd06d 298\r
299 //\r
300 // Enter critical section\r
301 //\r
302 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
c220787b
RN
303 \r
304 KeyboardTimerHandler (NULL, ConsoleIn);\r
05fbd06d 305\r
c220787b 306 if (!ConsoleIn->KeyboardErr) {\r
05fbd06d 307 //\r
c220787b
RN
308 // Someone is waiting on the keyboard event, if there's\r
309 // a key pending, signal the event\r
05fbd06d 310 //\r
c220787b
RN
311 if (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {\r
312 gBS->SignalEvent (Event);\r
313 }\r
05fbd06d 314 }\r
315 //\r
316 // Leave critical section and return\r
317 //\r
318 gBS->RestoreTPL (OldTpl);\r
05fbd06d 319}\r
320\r
bcd70414 321/**\r
322 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event\r
323 Signal the event if there is key available\r
324\r
325 @param Event event object\r
326 @param Context waiting context\r
327\r
328**/\r
f3d1e940 329VOID\r
330EFIAPI\r
331KeyboardWaitForKeyEx (\r
332 IN EFI_EVENT Event,\r
333 IN VOID *Context\r
334 )\r
f3d1e940 335\r
f3d1e940 336{\r
c220787b 337 KeyboardWaitForKey (Event, Context);\r
f3d1e940 338}\r
339\r
bcd70414 340/**\r
341 Reset the input device and optionaly run diagnostics\r
342\r
b6763e03 343 @param This Protocol instance pointer.\r
344 @param ExtendedVerification Driver may perform diagnostics on reset.\r
bcd70414 345\r
b6763e03 346 @retval EFI_SUCCESS The device was reset.\r
347 @retval EFI_DEVICE_ERROR The device is not functioning properly and could \r
bcd70414 348 not be reset.\r
349\r
350**/\r
f3d1e940 351EFI_STATUS\r
352EFIAPI\r
353KeyboardEfiResetEx (\r
354 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
355 IN BOOLEAN ExtendedVerification\r
356 )\r
f3d1e940 357\r
f3d1e940 358{\r
f3d1e940 359 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
f3d1e940 360\r
361 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); \r
f3d1e940 362\r
c220787b
RN
363 return ConsoleInDev->ConIn.Reset (\r
364 &ConsoleInDev->ConIn, \r
365 ExtendedVerification\r
366 );\r
f3d1e940 367}\r
368\r
bcd70414 369/**\r
f3d1e940 370 Reads the next keystroke from the input device. The WaitForKey Event can \r
371 be used to test for existance of a keystroke via WaitForEvent () call.\r
372\r
bcd70414 373\r
b6763e03 374 @param This Protocol instance pointer.\r
375 @param KeyData A pointer to a buffer that is filled in with the keystroke \r
376 state data for the key that was pressed.\r
f3d1e940 377\r
b6763e03 378 @retval EFI_SUCCESS The keystroke information was returned.\r
379 @retval EFI_NOT_READY There was no keystroke data availiable.\r
380 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to \r
381 hardware errors.\r
382 @retval EFI_INVALID_PARAMETER KeyData is NULL. \r
bcd70414 383\r
384**/\r
385EFI_STATUS\r
386EFIAPI\r
387KeyboardReadKeyStrokeEx (\r
388 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
389 OUT EFI_KEY_DATA *KeyData\r
390 )\r
f3d1e940 391\r
f3d1e940 392{\r
393 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
394\r
395 if (KeyData == NULL) {\r
396 return EFI_INVALID_PARAMETER;\r
397 }\r
398\r
399 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
400 return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);\r
401 \r
402}\r
403\r
bcd70414 404/**\r
405 Set certain state for the input device.\r
406\r
b6763e03 407 @param This Protocol instance pointer.\r
408 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
409 state for the input device.\r
bcd70414 410\r
b6763e03 411 @retval EFI_SUCCESS The device state was set successfully.\r
412 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could \r
413 not have the setting adjusted.\r
414 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
415 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. \r
bcd70414 416\r
417**/ \r
f3d1e940 418EFI_STATUS\r
419EFIAPI\r
420KeyboardSetState (\r
421 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
422 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
423 )\r
f3d1e940 424\r
f3d1e940 425{\r
426 EFI_STATUS Status;\r
427 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
428 EFI_TPL OldTpl;\r
429\r
430 if (KeyToggleState == NULL) {\r
431 return EFI_INVALID_PARAMETER;\r
432 }\r
433 \r
434 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
435\r
436 //\r
437 // Enter critical section\r
438 //\r
439 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
440\r
441 if (ConsoleInDev->KeyboardErr) {\r
442 Status = EFI_DEVICE_ERROR;\r
443 goto Exit;\r
444 }\r
445\r
c220787b 446 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
f3d1e940 447 Status = EFI_UNSUPPORTED;\r
448 goto Exit;\r
449 }\r
450 \r
451 //\r
452 // Update the status light\r
453 //\r
454 ConsoleInDev->ScrollLock = FALSE;\r
455 ConsoleInDev->NumLock = FALSE;\r
456 ConsoleInDev->CapsLock = FALSE;\r
457\r
458 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
459 ConsoleInDev->ScrollLock = TRUE;\r
460 } \r
461 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
462 ConsoleInDev->NumLock = TRUE;\r
463 }\r
464 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
465 ConsoleInDev->CapsLock = TRUE;\r
466 }\r
467\r
468 Status = UpdateStatusLights (ConsoleInDev);\r
469 if (EFI_ERROR (Status)) {\r
470 Status = EFI_DEVICE_ERROR; \r
471 }\r
472\r
f3d1e940 473Exit: \r
474 //\r
475 // Leave critical section and return\r
476 //\r
477 gBS->RestoreTPL (OldTpl);\r
478\r
479 return Status;\r
480\r
481}\r
bcd70414 482\r
483/**\r
484 Register a notification function for a particular keystroke for the input device.\r
485\r
b6763e03 486 @param This Protocol instance pointer.\r
487 @param KeyData A pointer to a buffer that is filled in with the keystroke \r
488 information data for the key that was pressed.\r
489 @param KeyNotificationFunction Points to the function to be called when the key \r
490 sequence is typed specified by KeyData. \r
491 @param NotifyHandle Points to the unique handle assigned to the registered notification. \r
bcd70414 492\r
b6763e03 493 @retval EFI_SUCCESS The notification function was registered successfully.\r
494 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
495 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL. \r
bcd70414 496 \r
497**/ \r
f3d1e940 498EFI_STATUS\r
499EFIAPI\r
500KeyboardRegisterKeyNotify (\r
501 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
502 IN EFI_KEY_DATA *KeyData,\r
503 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
504 OUT EFI_HANDLE *NotifyHandle\r
505 )\r
f3d1e940 506{\r
507 EFI_STATUS Status;\r
508 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
509 EFI_TPL OldTpl;\r
510 LIST_ENTRY *Link;\r
511 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
512 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
513\r
514 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
515 return EFI_INVALID_PARAMETER;\r
516 }\r
517 \r
518 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
519\r
520 //\r
521 // Enter critical section\r
522 //\r
523 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
524\r
525 //\r
526 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
527 //\r
528 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
529 CurrentNotify = CR (\r
530 Link, \r
531 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
532 NotifyEntry, \r
533 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
534 );\r
535 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
536 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
537 *NotifyHandle = CurrentNotify->NotifyHandle; \r
538 Status = EFI_SUCCESS;\r
539 goto Exit;\r
540 }\r
541 }\r
542 } \r
543 \r
544 //\r
545 // Allocate resource to save the notification function\r
546 // \r
547 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
548 if (NewNotify == NULL) {\r
549 Status = EFI_OUT_OF_RESOURCES;\r
550 goto Exit;\r
551 }\r
552\r
553 NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
554 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
7fc80d44 555 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
f3d1e940 556 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
557 InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);\r
558\r
f3d1e940 559 *NotifyHandle = NewNotify->NotifyHandle; \r
560 Status = EFI_SUCCESS;\r
561\r
562Exit:\r
563 //\r
564 // Leave critical section and return\r
565 //\r
566 gBS->RestoreTPL (OldTpl);\r
567 return Status; \r
568\r
569}\r
570\r
bcd70414 571/**\r
572 Remove a registered notification function from a particular keystroke.\r
573\r
b6763e03 574 @param This Protocol instance pointer. \r
575 @param NotificationHandle The handle of the notification function being unregistered.\r
bcd70414 576\r
577 \r
b6763e03 578 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
579 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
bcd70414 580 \r
581**/ \r
f3d1e940 582EFI_STATUS\r
583EFIAPI\r
584KeyboardUnregisterKeyNotify (\r
585 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
586 IN EFI_HANDLE NotificationHandle\r
587 )\r
f3d1e940 588{\r
589 EFI_STATUS Status;\r
590 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
591 EFI_TPL OldTpl;\r
592 LIST_ENTRY *Link;\r
593 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
594\r
595 if (NotificationHandle == NULL) {\r
596 return EFI_INVALID_PARAMETER;\r
597 } \r
0dc99784 598\r
599 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
600 return EFI_INVALID_PARAMETER;\r
601 } \r
602 \r
f3d1e940 603 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
604 \r
605 //\r
606 // Enter critical section\r
607 //\r
608 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); \r
609\r
610 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
611 CurrentNotify = CR (\r
612 Link, \r
613 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
614 NotifyEntry, \r
615 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
616 ); \r
617 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
618 //\r
619 // Remove the notification function from NotifyList and free resources\r
620 //\r
621 RemoveEntryList (&CurrentNotify->NotifyEntry); \r
7fc80d44 622 \r
f3d1e940 623 gBS->FreePool (CurrentNotify); \r
624 Status = EFI_SUCCESS;\r
625 goto Exit;\r
626 }\r
627 }\r
628\r
629 //\r
630 // Can not find the specified Notification Handle\r
631 //\r
8a67d804 632 Status = EFI_INVALID_PARAMETER;\r
f3d1e940 633Exit:\r
634 //\r
635 // Leave critical section and return\r
636 //\r
637 gBS->RestoreTPL (OldTpl);\r
638 return Status;\r
639}\r
640\r