]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
IntelFrameworkModulePkg: Update comments in SimpleTextInEx
[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
cc9a430c 5Copyright (c) 2006 - 2017, 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
cc9a430c
DB
536 information data for the key that was pressed. If KeyData.Key,\r
537 KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState\r
538 are 0, then any incomplete keystroke will trigger a notification of\r
539 the KeyNotificationFunction.\r
5829afe3 540 @param KeyNotificationFunction Points to the function to be called when the key\r
cc9a430c
DB
541 sequence is typed specified by KeyData. This notification function\r
542 should be called at <=TPL_CALLBACK.\r
5829afe3 543 @param NotifyHandle Points to the unique handle assigned to the registered notification.\r
bcd70414 544\r
b6763e03 545 @retval EFI_SUCCESS The notification function was registered successfully.\r
546 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
5829afe3 547 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.\r
548\r
549**/\r
f3d1e940 550EFI_STATUS\r
551EFIAPI\r
552KeyboardRegisterKeyNotify (\r
553 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
554 IN EFI_KEY_DATA *KeyData,\r
555 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
402e4a9d 556 OUT VOID **NotifyHandle\r
f3d1e940 557 )\r
f3d1e940 558{\r
559 EFI_STATUS Status;\r
560 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
561 EFI_TPL OldTpl;\r
562 LIST_ENTRY *Link;\r
5829afe3 563 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
f3d1e940 564 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
565\r
566 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
567 return EFI_INVALID_PARAMETER;\r
568 }\r
5829afe3 569\r
f3d1e940 570 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
571\r
572 //\r
573 // Enter critical section\r
574 //\r
575 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
576\r
577 //\r
578 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
579 //\r
580 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
581 CurrentNotify = CR (\r
5829afe3 582 Link,\r
583 KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
584 NotifyEntry,\r
f3d1e940 585 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
586 );\r
5829afe3 587 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
f3d1e940 588 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
402e4a9d 589 *NotifyHandle = CurrentNotify;\r
f3d1e940 590 Status = EFI_SUCCESS;\r
591 goto Exit;\r
592 }\r
593 }\r
5829afe3 594 }\r
595\r
f3d1e940 596 //\r
597 // Allocate resource to save the notification function\r
5829afe3 598 //\r
f3d1e940 599 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
600 if (NewNotify == NULL) {\r
601 Status = EFI_OUT_OF_RESOURCES;\r
602 goto Exit;\r
603 }\r
604\r
5829afe3 605 NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
f3d1e940 606 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
607 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
608 InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);\r
609\r
402e4a9d 610 *NotifyHandle = NewNotify;\r
f3d1e940 611 Status = EFI_SUCCESS;\r
612\r
613Exit:\r
614 //\r
615 // Leave critical section and return\r
616 //\r
617 gBS->RestoreTPL (OldTpl);\r
5829afe3 618 return Status;\r
f3d1e940 619\r
620}\r
621\r
bcd70414 622/**\r
623 Remove a registered notification function from a particular keystroke.\r
624\r
5829afe3 625 @param This Protocol instance pointer.\r
b6763e03 626 @param NotificationHandle The handle of the notification function being unregistered.\r
bcd70414 627\r
5829afe3 628\r
b6763e03 629 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
630 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
5829afe3 631\r
632**/\r
f3d1e940 633EFI_STATUS\r
634EFIAPI\r
635KeyboardUnregisterKeyNotify (\r
636 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
402e4a9d 637 IN VOID *NotificationHandle\r
f3d1e940 638 )\r
f3d1e940 639{\r
640 EFI_STATUS Status;\r
641 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
642 EFI_TPL OldTpl;\r
643 LIST_ENTRY *Link;\r
5829afe3 644 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
f3d1e940 645\r
646 if (NotificationHandle == NULL) {\r
647 return EFI_INVALID_PARAMETER;\r
5829afe3 648 }\r
0dc99784 649\r
f3d1e940 650 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
5829afe3 651\r
f3d1e940 652 //\r
653 // Enter critical section\r
654 //\r
5829afe3 655 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
f3d1e940 656\r
657 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
658 CurrentNotify = CR (\r
5829afe3 659 Link,\r
660 KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
661 NotifyEntry,\r
f3d1e940 662 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
5829afe3 663 );\r
402e4a9d 664 if (CurrentNotify == NotificationHandle) {\r
f3d1e940 665 //\r
666 // Remove the notification function from NotifyList and free resources\r
667 //\r
5829afe3 668 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
669\r
670 gBS->FreePool (CurrentNotify);\r
f3d1e940 671 Status = EFI_SUCCESS;\r
672 goto Exit;\r
673 }\r
674 }\r
675\r
676 //\r
677 // Can not find the specified Notification Handle\r
678 //\r
8a67d804 679 Status = EFI_INVALID_PARAMETER;\r
f3d1e940 680Exit:\r
681 //\r
682 // Leave critical section and return\r
683 //\r
684 gBS->RestoreTPL (OldTpl);\r
685 return Status;\r
686}\r
687\r
7863d11c
SZ
688/**\r
689 Process key notify.\r
690\r
691 @param Event Indicates the event that invoke this function.\r
692 @param Context Indicates the calling context.\r
693**/\r
694VOID\r
695EFIAPI\r
696KeyNotifyProcessHandler (\r
697 IN EFI_EVENT Event,\r
698 IN VOID *Context\r
699 )\r
700{\r
701 EFI_STATUS Status;\r
702 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
703 EFI_KEY_DATA KeyData;\r
704 LIST_ENTRY *Link;\r
705 LIST_ENTRY *NotifyList;\r
706 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
707 EFI_TPL OldTpl;\r
708\r
709 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
710\r
711 //\r
712 // Invoke notification functions.\r
713 //\r
714 NotifyList = &ConsoleIn->NotifyList;\r
715 while (TRUE) {\r
716 //\r
717 // Enter critical section\r
718 // \r
719 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
720 Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);\r
721 //\r
722 // Leave critical section\r
723 //\r
724 gBS->RestoreTPL (OldTpl);\r
725 if (EFI_ERROR (Status)) {\r
726 break;\r
727 }\r
728 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
729 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
730 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
731 CurrentNotify->KeyNotificationFn (&KeyData);\r
732 }\r
733 }\r
734 }\r
735}\r
736\r