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