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