]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
IntelFrameworkModulePkg Ps2KbDxe: Execute key notify func at TPL_CALLBACK
[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
7863d11c 5Copyright (c) 2006 - 2016, 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
c220787b
RN
35/**\r
36 Read & remove one key data from the EFI key buffer.\r
5829afe3 37\r
c220787b
RN
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
b6763e03 43**/\r
05fbd06d 44EFI_STATUS\r
c220787b
RN
45PopEfikeyBufHead (\r
46 IN EFI_KEY_QUEUE *Queue,\r
5829afe3 47 OUT EFI_KEY_DATA *KeyData OPTIONAL\r
b6763e03 48 )\r
49{\r
c220787b
RN
50 if (IsEfikeyBufEmpty (Queue)) {\r
51 return EFI_NOT_READY;\r
52 }\r
b6763e03 53 //\r
c220787b 54 // Retrieve and remove the values\r
b6763e03 55 //\r
5829afe3 56 if (KeyData != NULL) {\r
57 CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));\r
58 }\r
c220787b 59 Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;\r
b6763e03 60 return EFI_SUCCESS;\r
61}\r
05fbd06d 62\r
5829afe3 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
bcd70414 85/**\r
b6763e03 86 Judge whether is a registed key\r
87\r
5829afe3 88 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke\r
b6763e03 89 state data for the key that was registered.\r
5829afe3 90 @param InputData A pointer to a buffer that is filled in with the keystroke\r
b6763e03 91 state data for the key that was pressed.\r
bcd70414 92\r
b6763e03 93 @retval TRUE Key be pressed matches a registered key.\r
5829afe3 94 @retval FLASE Match failed.\r
95\r
bcd70414 96**/\r
f3d1e940 97BOOLEAN\r
98IsKeyRegistered (\r
99 IN EFI_KEY_DATA *RegsiteredData,\r
100 IN EFI_KEY_DATA *InputData\r
b6763e03 101 )\r
102\r
103{\r
104 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
5829afe3 105\r
b6763e03 106 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
107 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
5829afe3 108 return FALSE;\r
109 }\r
110\r
b6763e03 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
5829afe3 116 return FALSE;\r
117 }\r
b6763e03 118 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
119 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
5829afe3 120 return FALSE;\r
121 }\r
122\r
b6763e03 123 return TRUE;\r
124\r
125}\r
f3d1e940 126\r
bcd70414 127/**\r
5829afe3 128 Reads the next keystroke from the input device. The WaitForKey Event can\r
bcd70414 129 be used to test for existance of a keystroke via WaitForEvent () call.\r
5829afe3 130\r
b6763e03 131 @param ConsoleInDev Ps2 Keyboard private structure\r
5829afe3 132 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
b6763e03 133 state data for the key that was pressed.\r
f3d1e940 134\r
5829afe3 135\r
b6763e03 136 @retval EFI_SUCCESS The keystroke information was returned.\r
137 @retval EFI_NOT_READY There was no keystroke data availiable.\r
5829afe3 138 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
b6763e03 139 hardware errors.\r
5829afe3 140 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
bcd70414 141\r
142**/\r
f3d1e940 143EFI_STATUS\r
144KeyboardReadKeyStrokeWorker (\r
145 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev,\r
146 OUT EFI_KEY_DATA *KeyData\r
147 )\r
f3d1e940 148\r
f3d1e940 149{\r
150 EFI_STATUS Status;\r
151 EFI_TPL OldTpl;\r
5829afe3 152\r
f3d1e940 153 if (KeyData == NULL) {\r
154 return EFI_INVALID_PARAMETER;\r
155 }\r
5829afe3 156\r
f3d1e940 157 //\r
158 // Enter critical section\r
159 //\r
160 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
161\r
c220787b 162 KeyboardTimerHandler (NULL, ConsoleInDev);\r
5829afe3 163\r
c220787b
RN
164 if (ConsoleInDev->KeyboardErr) {\r
165 Status = EFI_DEVICE_ERROR;\r
166 } else {\r
167 Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);\r
f3d1e940 168 }\r
169\r
c220787b
RN
170 gBS->RestoreTPL (OldTpl);\r
171 return Status;\r
f3d1e940 172}\r
173\r
bcd70414 174/**\r
b6763e03 175 Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()\r
bcd70414 176\r
b6763e03 177 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
5829afe3 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
bcd70414 181\r
182**/\r
05fbd06d 183EFI_STATUS\r
184EFIAPI\r
185KeyboardEfiReset (\r
186 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
187 IN BOOLEAN ExtendedVerification\r
188 )\r
05fbd06d 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
05fbd06d 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
f713c4fe 240 if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) {\r
05fbd06d 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
bcd70414 251/**\r
b6763e03 252 Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().\r
bcd70414 253\r
254 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
5829afe3 255 @param Key The output buffer for key value\r
bcd70414 256\r
257 @retval EFI_SUCCESS success to read key stroke\r
258**/\r
05fbd06d 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
05fbd06d 265{\r
266 EFI_STATUS Status;\r
267 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
f3d1e940 268 EFI_KEY_DATA KeyData;\r
05fbd06d 269\r
270 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
f3d1e940 271 \r
5829afe3 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
9891f791
RN
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
5829afe3 303 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
304 return EFI_SUCCESS;\r
305 }\r
05fbd06d 306}\r
307\r
bcd70414 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
05fbd06d 316VOID\r
317EFIAPI\r
318KeyboardWaitForKey (\r
319 IN EFI_EVENT Event,\r
320 IN VOID *Context\r
321 )\r
05fbd06d 322{\r
c220787b
RN
323 EFI_TPL OldTpl;\r
324 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
5829afe3 325 EFI_KEY_DATA KeyData;\r
05fbd06d 326\r
c220787b 327 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
05fbd06d 328\r
329 //\r
330 // Enter critical section\r
331 //\r
332 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
5829afe3 333\r
c220787b 334 KeyboardTimerHandler (NULL, ConsoleIn);\r
05fbd06d 335\r
c220787b 336 if (!ConsoleIn->KeyboardErr) {\r
05fbd06d 337 //\r
5829afe3 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
05fbd06d 342 //\r
5829afe3 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
c220787b 356 gBS->SignalEvent (Event);\r
5829afe3 357 break;\r
c220787b 358 }\r
05fbd06d 359 }\r
360 //\r
361 // Leave critical section and return\r
362 //\r
363 gBS->RestoreTPL (OldTpl);\r
05fbd06d 364}\r
365\r
bcd70414 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
f3d1e940 374VOID\r
375EFIAPI\r
376KeyboardWaitForKeyEx (\r
377 IN EFI_EVENT Event,\r
378 IN VOID *Context\r
379 )\r
f3d1e940 380\r
f3d1e940 381{\r
c220787b 382 KeyboardWaitForKey (Event, Context);\r
f3d1e940 383}\r
384\r
bcd70414 385/**\r
386 Reset the input device and optionaly run diagnostics\r
387\r
b6763e03 388 @param This Protocol instance pointer.\r
389 @param ExtendedVerification Driver may perform diagnostics on reset.\r
bcd70414 390\r
b6763e03 391 @retval EFI_SUCCESS The device was reset.\r
5829afe3 392 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
bcd70414 393 not be reset.\r
394\r
395**/\r
f3d1e940 396EFI_STATUS\r
397EFIAPI\r
398KeyboardEfiResetEx (\r
399 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
400 IN BOOLEAN ExtendedVerification\r
401 )\r
f3d1e940 402\r
f3d1e940 403{\r
f3d1e940 404 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
f3d1e940 405\r
5829afe3 406 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
f3d1e940 407\r
c220787b 408 return ConsoleInDev->ConIn.Reset (\r
5829afe3 409 &ConsoleInDev->ConIn,\r
c220787b
RN
410 ExtendedVerification\r
411 );\r
f3d1e940 412}\r
413\r
bcd70414 414/**\r
5829afe3 415 Reads the next keystroke from the input device. The WaitForKey Event can\r
f3d1e940 416 be used to test for existance of a keystroke via WaitForEvent () call.\r
417\r
bcd70414 418\r
b6763e03 419 @param This Protocol instance pointer.\r
5829afe3 420 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
b6763e03 421 state data for the key that was pressed.\r
f3d1e940 422\r
b6763e03 423 @retval EFI_SUCCESS The keystroke information was returned.\r
424 @retval EFI_NOT_READY There was no keystroke data availiable.\r
5829afe3 425 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
b6763e03 426 hardware errors.\r
5829afe3 427 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
bcd70414 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
f3d1e940 436\r
f3d1e940 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
f3d1e940 446}\r
447\r
bcd70414 448/**\r
449 Set certain state for the input device.\r
450\r
b6763e03 451 @param This Protocol instance pointer.\r
5829afe3 452 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
b6763e03 453 state for the input device.\r
bcd70414 454\r
b6763e03 455 @retval EFI_SUCCESS The device state was set successfully.\r
5829afe3 456 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could\r
b6763e03 457 not have the setting adjusted.\r
458 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
5829afe3 459 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
bcd70414 460\r
5829afe3 461**/\r
f3d1e940 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
f3d1e940 468\r
f3d1e940 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
5829afe3 477\r
f3d1e940 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
c220787b 490 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
f3d1e940 491 Status = EFI_UNSUPPORTED;\r
492 goto Exit;\r
493 }\r
5829afe3 494\r
f3d1e940 495 //\r
496 // Update the status light\r
497 //\r
5829afe3 498 ConsoleInDev->ScrollLock = FALSE;\r
499 ConsoleInDev->NumLock = FALSE;\r
500 ConsoleInDev->CapsLock = FALSE;\r
501 ConsoleInDev->IsSupportPartialKey = FALSE;\r
f3d1e940 502\r
503 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
504 ConsoleInDev->ScrollLock = TRUE;\r
5829afe3 505 }\r
f3d1e940 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
5829afe3 512 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {\r
513 ConsoleInDev->IsSupportPartialKey = TRUE;\r
514 }\r
f3d1e940 515\r
516 Status = UpdateStatusLights (ConsoleInDev);\r
517 if (EFI_ERROR (Status)) {\r
5829afe3 518 Status = EFI_DEVICE_ERROR;\r
f3d1e940 519 }\r
520\r
5829afe3 521Exit:\r
f3d1e940 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
bcd70414 530\r
531/**\r
532 Register a notification function for a particular keystroke for the input device.\r
533\r
b6763e03 534 @param This Protocol instance pointer.\r
5829afe3 535 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
b6763e03 536 information data for the key that was pressed.\r
5829afe3 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
bcd70414 540\r
b6763e03 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
5829afe3 543 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.\r
544\r
545**/\r
f3d1e940 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
402e4a9d 552 OUT VOID **NotifyHandle\r
f3d1e940 553 )\r
f3d1e940 554{\r
555 EFI_STATUS Status;\r
556 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
557 EFI_TPL OldTpl;\r
558 LIST_ENTRY *Link;\r
5829afe3 559 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
f3d1e940 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
5829afe3 565\r
f3d1e940 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
5829afe3 578 Link,\r
579 KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
580 NotifyEntry,\r
f3d1e940 581 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
582 );\r
5829afe3 583 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
f3d1e940 584 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
402e4a9d 585 *NotifyHandle = CurrentNotify;\r
f3d1e940 586 Status = EFI_SUCCESS;\r
587 goto Exit;\r
588 }\r
589 }\r
5829afe3 590 }\r
591\r
f3d1e940 592 //\r
593 // Allocate resource to save the notification function\r
5829afe3 594 //\r
f3d1e940 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
5829afe3 601 NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
f3d1e940 602 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
603 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
604 InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);\r
605\r
402e4a9d 606 *NotifyHandle = NewNotify;\r
f3d1e940 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
5829afe3 614 return Status;\r
f3d1e940 615\r
616}\r
617\r
bcd70414 618/**\r
619 Remove a registered notification function from a particular keystroke.\r
620\r
5829afe3 621 @param This Protocol instance pointer.\r
b6763e03 622 @param NotificationHandle The handle of the notification function being unregistered.\r
bcd70414 623\r
5829afe3 624\r
b6763e03 625 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
626 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
5829afe3 627\r
628**/\r
f3d1e940 629EFI_STATUS\r
630EFIAPI\r
631KeyboardUnregisterKeyNotify (\r
632 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
402e4a9d 633 IN VOID *NotificationHandle\r
f3d1e940 634 )\r
f3d1e940 635{\r
636 EFI_STATUS Status;\r
637 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
638 EFI_TPL OldTpl;\r
639 LIST_ENTRY *Link;\r
5829afe3 640 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
f3d1e940 641\r
642 if (NotificationHandle == NULL) {\r
643 return EFI_INVALID_PARAMETER;\r
5829afe3 644 }\r
0dc99784 645\r
f3d1e940 646 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
5829afe3 647\r
f3d1e940 648 //\r
649 // Enter critical section\r
650 //\r
5829afe3 651 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
f3d1e940 652\r
653 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
654 CurrentNotify = CR (\r
5829afe3 655 Link,\r
656 KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
657 NotifyEntry,\r
f3d1e940 658 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
5829afe3 659 );\r
402e4a9d 660 if (CurrentNotify == NotificationHandle) {\r
f3d1e940 661 //\r
662 // Remove the notification function from NotifyList and free resources\r
663 //\r
5829afe3 664 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
665\r
666 gBS->FreePool (CurrentNotify);\r
f3d1e940 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
8a67d804 675 Status = EFI_INVALID_PARAMETER;\r
f3d1e940 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
7863d11c
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