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