]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
Fix the PS2 keyboard driver to call hotkey callback even no one is calling ReadKeyStroke
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdCtrller.c
CommitLineData
f713c4fe 1/** @file\r
05fbd06d 2 Routines that access 8042 keyboard controller\r
3\r
c220787b 4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
180a5a35 5This program and the accompanying materials\r
df0dcb5e 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
05fbd06d 12\r
13**/\r
14\r
05fbd06d 15#include "Ps2Keyboard.h"\r
16\r
819d1488 17struct {\r
67319626 18 UINT8 ScanCode; ///< follows value defined in Scan Code Set1\r
05fbd06d 19 UINT16 EfiScanCode;\r
20 CHAR16 UnicodeChar;\r
21 CHAR16 ShiftUnicodeChar;\r
22}\r
23ConvertKeyboardScanCodeToEfiKey[] = {\r
24\r
25 {\r
26 0x01, // Escape\r
27 SCAN_ESC,\r
67319626 28 0x0000,\r
29 0x0000\r
05fbd06d 30 },\r
31 {\r
32 0x02,\r
33 SCAN_NULL,\r
67319626 34 L'1',\r
35 L'!'\r
05fbd06d 36 },\r
37 {\r
38 0x03,\r
39 SCAN_NULL,\r
67319626 40 L'2',\r
41 L'@'\r
05fbd06d 42 },\r
43 {\r
44 0x04,\r
45 SCAN_NULL,\r
67319626 46 L'3',\r
47 L'#'\r
05fbd06d 48 },\r
49 {\r
50 0x05,\r
51 SCAN_NULL,\r
67319626 52 L'4',\r
53 L'$'\r
05fbd06d 54 },\r
55 {\r
56 0x06,\r
57 SCAN_NULL,\r
67319626 58 L'5',\r
59 L'%'\r
05fbd06d 60 },\r
61 {\r
62 0x07,\r
63 SCAN_NULL,\r
67319626 64 L'6',\r
65 L'^'\r
05fbd06d 66 },\r
67 {\r
68 0x08,\r
69 SCAN_NULL,\r
67319626 70 L'7',\r
71 L'&'\r
05fbd06d 72 },\r
73 {\r
74 0x09,\r
75 SCAN_NULL,\r
67319626 76 L'8',\r
77 L'*'\r
05fbd06d 78 },\r
79 {\r
80 0x0A,\r
81 SCAN_NULL,\r
67319626 82 L'9',\r
83 L'('\r
05fbd06d 84 },\r
85 {\r
86 0x0B,\r
87 SCAN_NULL,\r
67319626 88 L'0',\r
89 L')'\r
05fbd06d 90 },\r
91 {\r
92 0x0C,\r
93 SCAN_NULL,\r
67319626 94 L'-',\r
95 L'_'\r
05fbd06d 96 },\r
97 {\r
98 0x0D,\r
99 SCAN_NULL,\r
67319626 100 L'=',\r
101 L'+'\r
05fbd06d 102 },\r
103 {\r
104 0x0E, // BackSpace\r
105 SCAN_NULL,\r
67319626 106 0x0008,\r
107 0x0008\r
05fbd06d 108 },\r
109 {\r
110 0x0F, // Tab\r
111 SCAN_NULL,\r
67319626 112 0x0009,\r
113 0x0009\r
05fbd06d 114 },\r
115 {\r
116 0x10,\r
117 SCAN_NULL,\r
67319626 118 L'q',\r
119 L'Q'\r
05fbd06d 120 },\r
121 {\r
122 0x11,\r
123 SCAN_NULL,\r
67319626 124 L'w',\r
125 L'W'\r
05fbd06d 126 },\r
127 {\r
128 0x12,\r
129 SCAN_NULL,\r
67319626 130 L'e',\r
131 L'E'\r
05fbd06d 132 },\r
133 {\r
134 0x13,\r
135 SCAN_NULL,\r
67319626 136 L'r',\r
137 L'R'\r
05fbd06d 138 },\r
139 {\r
140 0x14,\r
141 SCAN_NULL,\r
67319626 142 L't',\r
143 L'T'\r
05fbd06d 144 },\r
145 {\r
146 0x15,\r
147 SCAN_NULL,\r
67319626 148 L'y',\r
149 L'Y'\r
05fbd06d 150 },\r
151 {\r
152 0x16,\r
153 SCAN_NULL,\r
67319626 154 L'u',\r
155 L'U'\r
05fbd06d 156 },\r
157 {\r
158 0x17,\r
159 SCAN_NULL,\r
67319626 160 L'i',\r
161 L'I'\r
05fbd06d 162 },\r
163 {\r
164 0x18,\r
165 SCAN_NULL,\r
67319626 166 L'o',\r
167 L'O'\r
05fbd06d 168 },\r
169 {\r
170 0x19,\r
171 SCAN_NULL,\r
67319626 172 L'p',\r
173 L'P'\r
05fbd06d 174 },\r
175 {\r
176 0x1a,\r
177 SCAN_NULL,\r
67319626 178 L'[',\r
179 L'{'\r
05fbd06d 180 },\r
181 {\r
182 0x1b,\r
183 SCAN_NULL,\r
67319626 184 L']',\r
185 L'}'\r
05fbd06d 186 },\r
187 {\r
188 0x1c, // Enter\r
189 SCAN_NULL,\r
67319626 190 0x000d,\r
191 0x000d\r
05fbd06d 192 },\r
193 {\r
194 0x1d,\r
195 SCAN_NULL,\r
67319626 196 0x0000,\r
197 0x0000\r
05fbd06d 198 },\r
199 {\r
200 0x1e,\r
201 SCAN_NULL,\r
67319626 202 L'a',\r
203 L'A'\r
05fbd06d 204 },\r
205 {\r
206 0x1f,\r
207 SCAN_NULL,\r
67319626 208 L's',\r
209 L'S'\r
05fbd06d 210 },\r
211 {\r
212 0x20,\r
213 SCAN_NULL,\r
67319626 214 L'd',\r
215 L'D'\r
05fbd06d 216 },\r
217 {\r
218 0x21,\r
219 SCAN_NULL,\r
67319626 220 L'f',\r
221 L'F'\r
05fbd06d 222 },\r
223 {\r
224 0x22,\r
225 SCAN_NULL,\r
67319626 226 L'g',\r
227 L'G'\r
05fbd06d 228 },\r
229 {\r
230 0x23,\r
231 SCAN_NULL,\r
67319626 232 L'h',\r
233 L'H'\r
05fbd06d 234 },\r
235 {\r
236 0x24,\r
237 SCAN_NULL,\r
67319626 238 L'j',\r
239 L'J'\r
05fbd06d 240 },\r
241 {\r
242 0x25,\r
243 SCAN_NULL,\r
67319626 244 L'k',\r
245 L'K'\r
05fbd06d 246 },\r
247 {\r
248 0x26,\r
249 SCAN_NULL,\r
67319626 250 L'l',\r
251 L'L'\r
05fbd06d 252 },\r
253 {\r
254 0x27,\r
255 SCAN_NULL,\r
67319626 256 L';',\r
257 L':'\r
05fbd06d 258 },\r
259 {\r
260 0x28,\r
261 SCAN_NULL,\r
67319626 262 L'\'',\r
263 L'"'\r
05fbd06d 264 },\r
265 {\r
266 0x29,\r
267 SCAN_NULL,\r
67319626 268 L'`',\r
269 L'~'\r
05fbd06d 270 },\r
271 {\r
272 0x2a, // Left Shift\r
273 SCAN_NULL,\r
67319626 274 0x0000,\r
275 0x0000\r
05fbd06d 276 },\r
277 {\r
278 0x2b,\r
279 SCAN_NULL,\r
67319626 280 L'\\',\r
281 L'|'\r
05fbd06d 282 },\r
283 {\r
284 0x2c,\r
285 SCAN_NULL,\r
67319626 286 L'z',\r
287 L'Z'\r
05fbd06d 288 },\r
289 {\r
290 0x2d,\r
291 SCAN_NULL,\r
67319626 292 L'x',\r
293 L'X'\r
05fbd06d 294 },\r
295 {\r
296 0x2e,\r
297 SCAN_NULL,\r
67319626 298 L'c',\r
299 L'C'\r
05fbd06d 300 },\r
301 {\r
302 0x2f,\r
303 SCAN_NULL,\r
67319626 304 L'v',\r
305 L'V'\r
05fbd06d 306 },\r
307 {\r
308 0x30,\r
309 SCAN_NULL,\r
67319626 310 L'b',\r
311 L'B'\r
05fbd06d 312 },\r
313 {\r
314 0x31,\r
315 SCAN_NULL,\r
67319626 316 L'n',\r
317 L'N'\r
05fbd06d 318 },\r
319 {\r
320 0x32,\r
321 SCAN_NULL,\r
67319626 322 L'm',\r
323 L'M'\r
05fbd06d 324 },\r
325 {\r
326 0x33,\r
327 SCAN_NULL,\r
67319626 328 L',',\r
329 L'<'\r
05fbd06d 330 },\r
331 {\r
332 0x34,\r
333 SCAN_NULL,\r
67319626 334 L'.',\r
335 L'>'\r
05fbd06d 336 },\r
337 {\r
338 0x35,\r
339 SCAN_NULL,\r
67319626 340 L'/',\r
341 L'?'\r
05fbd06d 342 },\r
343 {\r
344 0x36, //Right Shift\r
345 SCAN_NULL,\r
67319626 346 0x0000,\r
347 0x0000\r
05fbd06d 348 },\r
349 {\r
350 0x37, // Numeric Keypad *\r
351 SCAN_NULL,\r
67319626 352 L'*',\r
353 L'*'\r
05fbd06d 354 },\r
355 {\r
356 0x38, //Left Alt/Extended Right Alt\r
357 SCAN_NULL,\r
67319626 358 0x0000,\r
359 0x0000\r
05fbd06d 360 },\r
361 {\r
362 0x39,\r
363 SCAN_NULL,\r
67319626 364 L' ',\r
365 L' '\r
05fbd06d 366 },\r
367 {\r
368 0x3A, //CapsLock\r
369 SCAN_NULL,\r
67319626 370 0x0000,\r
371 0x0000\r
05fbd06d 372 },\r
373 {\r
374 0x3B,\r
375 SCAN_F1,\r
67319626 376 0x0000,\r
377 0x0000\r
05fbd06d 378 },\r
379 {\r
380 0x3C,\r
381 SCAN_F2,\r
67319626 382 0x0000,\r
383 0x0000\r
05fbd06d 384 },\r
385 {\r
386 0x3D,\r
387 SCAN_F3,\r
67319626 388 0x0000,\r
389 0x0000\r
05fbd06d 390 },\r
391 {\r
392 0x3E,\r
393 SCAN_F4,\r
67319626 394 0x0000,\r
395 0x0000\r
05fbd06d 396 },\r
397 {\r
398 0x3F,\r
399 SCAN_F5,\r
67319626 400 0x0000,\r
401 0x0000\r
05fbd06d 402 },\r
403 {\r
404 0x40,\r
405 SCAN_F6,\r
67319626 406 0x0000,\r
407 0x0000\r
05fbd06d 408 },\r
409 {\r
410 0x41,\r
411 SCAN_F7,\r
67319626 412 0x0000,\r
413 0x0000\r
05fbd06d 414 },\r
415 {\r
416 0x42,\r
417 SCAN_F8,\r
67319626 418 0x0000,\r
419 0x0000\r
05fbd06d 420 },\r
421 {\r
422 0x43,\r
423 SCAN_F9,\r
67319626 424 0x0000,\r
425 0x0000\r
05fbd06d 426 },\r
427 {\r
428 0x44,\r
429 SCAN_F10,\r
67319626 430 0x0000,\r
431 0x0000\r
05fbd06d 432 },\r
433 {\r
434 0x45, // NumLock\r
435 SCAN_NULL,\r
67319626 436 0x0000,\r
437 0x0000\r
05fbd06d 438 },\r
439 {\r
440 0x46, // ScrollLock\r
441 SCAN_NULL,\r
67319626 442 0x0000,\r
443 0x0000\r
05fbd06d 444 },\r
445 {\r
446 0x47,\r
447 SCAN_HOME,\r
67319626 448 L'7',\r
449 L'7'\r
05fbd06d 450 },\r
451 {\r
452 0x48,\r
453 SCAN_UP,\r
67319626 454 L'8',\r
455 L'8'\r
05fbd06d 456 },\r
457 {\r
458 0x49,\r
459 SCAN_PAGE_UP,\r
67319626 460 L'9',\r
461 L'9'\r
05fbd06d 462 },\r
463 {\r
464 0x4a,\r
465 SCAN_NULL,\r
67319626 466 L'-',\r
467 L'-'\r
05fbd06d 468 },\r
469 {\r
470 0x4b,\r
471 SCAN_LEFT,\r
67319626 472 L'4',\r
473 L'4'\r
05fbd06d 474 },\r
475 {\r
476 0x4c, // Numeric Keypad 5\r
477 SCAN_NULL,\r
67319626 478 L'5',\r
479 L'5'\r
05fbd06d 480 },\r
481 {\r
482 0x4d,\r
483 SCAN_RIGHT,\r
67319626 484 L'6',\r
485 L'6'\r
05fbd06d 486 },\r
487 {\r
488 0x4e,\r
489 SCAN_NULL,\r
67319626 490 L'+',\r
491 L'+'\r
05fbd06d 492 },\r
493 {\r
494 0x4f,\r
495 SCAN_END,\r
67319626 496 L'1',\r
497 L'1'\r
05fbd06d 498 },\r
499 {\r
500 0x50,\r
501 SCAN_DOWN,\r
67319626 502 L'2',\r
503 L'2'\r
05fbd06d 504 },\r
505 {\r
506 0x51,\r
507 SCAN_PAGE_DOWN,\r
67319626 508 L'3',\r
509 L'3'\r
05fbd06d 510 },\r
511 {\r
512 0x52,\r
513 SCAN_INSERT,\r
67319626 514 L'0',\r
515 L'0'\r
05fbd06d 516 },\r
517 {\r
518 0x53,\r
519 SCAN_DELETE,\r
67319626 520 L'.',\r
521 L'.'\r
05fbd06d 522 },\r
523 {\r
524 0x57,\r
525 SCAN_F11,\r
67319626 526 0x0000,\r
527 0x0000\r
05fbd06d 528 },\r
529 {\r
530 0x58,\r
531 SCAN_F12,\r
67319626 532 0x0000,\r
533 0x0000\r
05fbd06d 534 },\r
f3d1e940 535 {\r
536 0x5B, //Left LOGO\r
537 SCAN_NULL,\r
67319626 538 0x0000,\r
539 0x0000\r
f3d1e940 540 }, \r
541 {\r
542 0x5C, //Right LOGO\r
543 SCAN_NULL,\r
67319626 544 0x0000,\r
545 0x0000\r
f3d1e940 546 }, \r
547 {\r
548 0x5D, //Menu key\r
549 SCAN_NULL,\r
67319626 550 0x0000,\r
551 0x0000\r
f3d1e940 552 }, \r
05fbd06d 553 {\r
554 TABLE_END,\r
555 TABLE_END,\r
556 SCAN_NULL,\r
557 SCAN_NULL\r
558 },\r
559};\r
560\r
05fbd06d 561//\r
562// The WaitForValue time out\r
563//\r
819d1488 564UINTN mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
05fbd06d 565\r
4fd730b3 566BOOLEAN mEnableMouseInterface;\r
567\r
c220787b
RN
568\r
569\r
570/**\r
571 Return the count of scancode in the queue.\r
572 \r
573 @param Queue Pointer to instance of SCAN_CODE_QUEUE.\r
574\r
575 @return Count of the scancode.\r
576**/\r
577UINTN\r
578GetScancodeBufCount (\r
579 IN SCAN_CODE_QUEUE *Queue\r
580 )\r
581{\r
582 if (Queue->Head <= Queue->Tail) {\r
583 return Queue->Tail - Queue->Head;\r
584 } else {\r
585 return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head;\r
586 }\r
587}\r
588\r
589/**\r
590 Read several bytes from the scancode buffer without removing them.\r
591 This function is called to see if there are enough bytes of scancode\r
592 representing a single key.\r
593 \r
594 @param Queue Pointer to instance of SCAN_CODE_QUEUE.\r
595 @param Count Number of bytes to be read\r
596 @param Buf Store the results\r
597\r
598 @retval EFI_SUCCESS success to scan the keyboard code\r
599 @retval EFI_NOT_READY invalid parameter\r
600**/\r
601EFI_STATUS\r
602GetScancodeBufHead (\r
603 IN SCAN_CODE_QUEUE *Queue,\r
604 IN UINTN Count,\r
605 OUT UINT8 *Buf\r
606 )\r
607{\r
608 UINTN Index;\r
609 UINTN Pos;\r
610\r
611 //\r
612 // check the valid range of parameter 'Count'\r
613 //\r
614 if (GetScancodeBufCount (Queue) < Count) {\r
615 return EFI_NOT_READY;\r
616 }\r
617 //\r
618 // retrieve the values\r
619 //\r
620 for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {\r
621 Buf[Index] = Queue->Buffer[Pos];\r
622 }\r
623\r
624 return EFI_SUCCESS;\r
625}\r
626\r
627/**\r
628 Push one byte to the scancode buffer.\r
629\r
630 @param Queue Pointer to instance of SCAN_CODE_QUEUE.\r
631 @param Scancode The byte to push.\r
632**/\r
633VOID\r
634PushScancodeBufTail (\r
635 IN SCAN_CODE_QUEUE *Queue,\r
636 IN UINT8 Scancode\r
637 )\r
638{\r
639 if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {\r
640 return;\r
641 }\r
642\r
643 Queue->Buffer[Queue->Tail] = Scancode;\r
644 Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;\r
645}\r
646\r
647/**\r
648\r
649 Read & remove several bytes from the scancode buffer.\r
650 This function is usually called after GetScancodeBufHead()\r
651 \r
652 @param Queue Pointer to instance of SCAN_CODE_QUEUE.\r
653 @param Count Number of bytes to be read\r
654 @param Buf Store the results\r
655\r
656 @retval EFI_SUCCESS success to scan the keyboard code\r
657 @retval EFI_NOT_READY invalid parameter\r
658**/\r
659EFI_STATUS\r
660PopScancodeBufHead (\r
661 IN SCAN_CODE_QUEUE *Queue,\r
662 IN UINTN Count,\r
663 OUT UINT8 *Buf\r
664 )\r
665{\r
666 UINTN Index;\r
667\r
668 //\r
669 // Check the valid range of parameter 'Count'\r
670 //\r
671 if (GetScancodeBufCount (Queue) < Count) {\r
672 return EFI_NOT_READY;\r
673 }\r
674 //\r
675 // Retrieve and remove the values\r
676 //\r
677 for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {\r
678 Buf[Index] = Queue->Buffer[Queue->Head];\r
679 }\r
680\r
681 return EFI_SUCCESS;\r
682}\r
683\r
bcd70414 684/**\r
f713c4fe 685 Read data register .\r
bcd70414 686\r
687 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
688\r
689 @return return the value \r
690\r
691**/\r
05fbd06d 692UINT8\r
693KeyReadDataRegister (\r
694 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
695 )\r
05fbd06d 696\r
05fbd06d 697{\r
698 EFI_ISA_IO_PROTOCOL *IsaIo;\r
699 UINT8 Data;\r
700\r
701 //\r
702 // Use IsaIo protocol to perform IO operations\r
703 //\r
704 IsaIo = ConsoleIn->IsaIo;\r
705\r
706 IsaIo->Io.Read (\r
707 IsaIo,\r
708 EfiIsaIoWidthUint8,\r
709 ConsoleIn->DataRegisterAddress,\r
710 1,\r
711 &Data\r
712 );\r
713\r
714 return Data;\r
715}\r
716\r
bcd70414 717/**\r
f713c4fe 718 Write data register.\r
bcd70414 719\r
720 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
721 @param Data value wanted to be written\r
722\r
723**/\r
05fbd06d 724VOID\r
725KeyWriteDataRegister (\r
726 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
727 IN UINT8 Data\r
728 )\r
05fbd06d 729{\r
c220787b
RN
730 ConsoleIn->IsaIo->Io.Write (\r
731 ConsoleIn->IsaIo,\r
732 EfiIsaIoWidthUint8,\r
733 ConsoleIn->DataRegisterAddress,\r
734 1,\r
735 &Data\r
736 );\r
05fbd06d 737}\r
738\r
bcd70414 739/**\r
f713c4fe 740 Read status register.\r
bcd70414 741\r
742 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
743\r
744 @return value in status register\r
745\r
746**/\r
05fbd06d 747UINT8\r
748KeyReadStatusRegister (\r
749 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
750 )\r
05fbd06d 751{\r
05fbd06d 752 UINT8 Data;\r
c220787b
RN
753 ConsoleIn->IsaIo->Io.Read (\r
754 ConsoleIn->IsaIo,\r
755 EfiIsaIoWidthUint8,\r
756 ConsoleIn->StatusRegisterAddress,\r
757 1,\r
758 &Data\r
759 );\r
05fbd06d 760 return Data;\r
05fbd06d 761}\r
762\r
bcd70414 763/**\r
f713c4fe 764 Write command register .\r
bcd70414 765\r
766 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
767 @param Data The value wanted to be written\r
768\r
769**/\r
05fbd06d 770VOID\r
771KeyWriteCommandRegister (\r
772 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
773 IN UINT8 Data\r
774 )\r
05fbd06d 775{\r
c220787b
RN
776 ConsoleIn->IsaIo->Io.Write (\r
777 ConsoleIn->IsaIo,\r
778 EfiIsaIoWidthUint8,\r
779 ConsoleIn->CommandRegisterAddress,\r
780 1,\r
781 &Data\r
782 );\r
05fbd06d 783}\r
784\r
bcd70414 785/**\r
f713c4fe 786 Display error message.\r
bcd70414 787\r
788 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
789 @param ErrMsg Unicode string of error message\r
790 \r
791**/\r
05fbd06d 792VOID\r
793KeyboardError (\r
794 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
795 IN CHAR16 *ErrMsg\r
796 )\r
05fbd06d 797{\r
798 ConsoleIn->KeyboardErr = TRUE;\r
05fbd06d 799}\r
800\r
bcd70414 801/**\r
05fbd06d 802 Timer event handler: read a series of scancodes from 8042\r
803 and put them into memory scancode buffer.\r
804 it read as much scancodes to either fill\r
805 the memory buffer or empty the keyboard buffer.\r
806 It is registered as running under TPL_NOTIFY\r
807\r
b6763e03 808 @param Event The timer event\r
809 @param Context A KEYBOARD_CONSOLE_IN_DEV pointer\r
05fbd06d 810\r
bcd70414 811**/\r
812VOID\r
813EFIAPI\r
814KeyboardTimerHandler (\r
815 IN EFI_EVENT Event,\r
816 IN VOID *Context\r
817 )\r
05fbd06d 818\r
05fbd06d 819{\r
820 UINT8 Data;\r
821 EFI_TPL OldTpl;\r
822 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
823\r
c220787b 824 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
05fbd06d 825\r
826 //\r
827 // Enter critical section\r
828 //\r
829 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
830\r
831 if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {\r
832 //\r
833 // Leave critical section and return\r
834 //\r
835 gBS->RestoreTPL (OldTpl);\r
836 return ;\r
837 }\r
b6763e03 838\r
05fbd06d 839 //\r
840 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that\r
c220787b
RN
841 // KB is not connected to system. If KB is not connected to system, driver will find there's something\r
842 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since\r
05fbd06d 843 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
844 // Just skip the 'resend' process simply.\r
845 //\r
846\r
c220787b
RN
847 while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) ==\r
848 KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA\r
849 ) {\r
05fbd06d 850 //\r
c220787b 851 // Read one byte of the scan code and store it into the memory buffer\r
05fbd06d 852 //\r
c220787b
RN
853 Data = KeyReadDataRegister (ConsoleIn);\r
854 PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data);\r
05fbd06d 855 }\r
c220787b 856 KeyGetchar (ConsoleIn);\r
05fbd06d 857\r
05fbd06d 858 //\r
859 // Leave critical section and return\r
860 //\r
861 gBS->RestoreTPL (OldTpl);\r
05fbd06d 862}\r
863\r
bcd70414 864/**\r
f713c4fe 865 Read key value .\r
bcd70414 866\r
867 @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
868 @param Data - Pointer to outof buffer for keeping key value\r
869\r
870 @retval EFI_TIMEOUT Status resigter time out\r
871 @retval EFI_SUCCESS Success to read keyboard\r
872\r
873**/\r
05fbd06d 874EFI_STATUS\r
875KeyboardRead (\r
876 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
877 OUT UINT8 *Data\r
878 )\r
05fbd06d 879\r
05fbd06d 880{\r
881 UINT32 TimeOut;\r
882 UINT32 RegFilled;\r
883\r
884 TimeOut = 0;\r
885 RegFilled = 0;\r
886\r
887 //\r
888 // wait till output buffer full then perform the read\r
889 //\r
890 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
b6763e03 891 if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {\r
05fbd06d 892 RegFilled = 1;\r
893 *Data = KeyReadDataRegister (ConsoleIn);\r
894 break;\r
895 }\r
896\r
b6763e03 897 MicroSecondDelay (30);\r
05fbd06d 898 }\r
899\r
f713c4fe 900 if (RegFilled == 0) {\r
05fbd06d 901 return EFI_TIMEOUT;\r
902 }\r
903\r
904 return EFI_SUCCESS;\r
905}\r
906\r
bcd70414 907/**\r
908 write key to keyboard\r
909\r
910 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
911 @param Data value wanted to be written\r
912\r
b6763e03 913 @retval EFI_TIMEOUT The input buffer register is full for putting new value util timeout\r
914 @retval EFI_SUCCESS The new value is sucess put into input buffer register.\r
bcd70414 915\r
916**/\r
05fbd06d 917EFI_STATUS\r
918KeyboardWrite (\r
919 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
920 IN UINT8 Data\r
921 )\r
05fbd06d 922{\r
923 UINT32 TimeOut;\r
924 UINT32 RegEmptied;\r
925\r
926 TimeOut = 0;\r
927 RegEmptied = 0;\r
928\r
929 //\r
930 // wait for input buffer empty\r
931 //\r
932 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
f713c4fe 933 if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {\r
05fbd06d 934 RegEmptied = 1;\r
935 break;\r
936 }\r
937\r
b6763e03 938 MicroSecondDelay (30);\r
05fbd06d 939 }\r
940\r
f713c4fe 941 if (RegEmptied == 0) {\r
05fbd06d 942 return EFI_TIMEOUT;\r
943 }\r
944 //\r
945 // Write it\r
946 //\r
947 KeyWriteDataRegister (ConsoleIn, Data);\r
948\r
949 return EFI_SUCCESS;\r
950}\r
951\r
bcd70414 952/**\r
f713c4fe 953 Issue keyboard command.\r
bcd70414 954\r
955 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
956 @param Data The buff holding the command \r
957\r
958 @retval EFI_TIMEOUT Keyboard is not ready to issuing \r
959 @retval EFI_SUCCESS Success to issue keyboard command\r
960\r
961**/\r
05fbd06d 962EFI_STATUS\r
963KeyboardCommand (\r
964 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
965 IN UINT8 Data\r
966 )\r
05fbd06d 967{\r
968 UINT32 TimeOut;\r
969 UINT32 RegEmptied;\r
970\r
971 TimeOut = 0;\r
972 RegEmptied = 0;\r
973\r
974 //\r
975 // Wait For Input Buffer Empty\r
976 //\r
977 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
f713c4fe 978 if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {\r
05fbd06d 979 RegEmptied = 1;\r
980 break;\r
981 }\r
982\r
b6763e03 983 MicroSecondDelay (30);\r
05fbd06d 984 }\r
985\r
f713c4fe 986 if (RegEmptied == 0) {\r
05fbd06d 987 return EFI_TIMEOUT;\r
988 }\r
989 //\r
990 // issue the command\r
991 //\r
992 KeyWriteCommandRegister (ConsoleIn, Data);\r
993\r
994 //\r
995 // Wait For Input Buffer Empty again\r
996 //\r
997 RegEmptied = 0;\r
998 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
f713c4fe 999 if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {\r
05fbd06d 1000 RegEmptied = 1;\r
1001 break;\r
1002 }\r
1003\r
b6763e03 1004 MicroSecondDelay (30);\r
05fbd06d 1005 }\r
1006\r
f713c4fe 1007 if (RegEmptied == 0) {\r
05fbd06d 1008 return EFI_TIMEOUT;\r
1009 }\r
1010\r
1011 return EFI_SUCCESS;\r
1012}\r
1013\r
bcd70414 1014/**\r
1015 wait for a specific value to be presented on\r
1016 8042 Data register by keyboard and then read it,\r
1017 used in keyboard commands ack\r
1018\r
1019 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
1020 @param Value the value wanted to be waited.\r
1021\r
1022 @retval EFI_TIMEOUT Fail to get specific value in given time\r
1023 @retval EFI_SUCCESS Success to get specific value in given time.\r
1024 \r
1025**/\r
05fbd06d 1026EFI_STATUS\r
1027KeyboardWaitForValue (\r
1028 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1029 IN UINT8 Value\r
1030 )\r
05fbd06d 1031{\r
1032 UINT8 Data;\r
1033 UINT32 TimeOut;\r
1034 UINT32 SumTimeOut;\r
1035 UINT32 GotIt;\r
1036\r
1037 GotIt = 0;\r
1038 TimeOut = 0;\r
1039 SumTimeOut = 0;\r
1040\r
1041 //\r
1042 // Make sure the initial value of 'Data' is different from 'Value'\r
1043 //\r
1044 Data = 0;\r
1045 if (Data == Value) {\r
1046 Data = 1;\r
1047 }\r
1048 //\r
1049 // Read from 8042 (multiple times if needed)\r
1050 // until the expected value appears\r
1051 // use SumTimeOut to control the iteration\r
1052 //\r
1053 while (1) {\r
1054 //\r
1055 // Perform a read\r
1056 //\r
1057 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1058 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {\r
1059 Data = KeyReadDataRegister (ConsoleIn);\r
1060 break;\r
1061 }\r
1062\r
b6763e03 1063 MicroSecondDelay (30);\r
05fbd06d 1064 }\r
1065\r
1066 SumTimeOut += TimeOut;\r
1067\r
1068 if (Data == Value) {\r
1069 GotIt = 1;\r
1070 break;\r
1071 }\r
1072\r
1073 if (SumTimeOut >= mWaitForValueTimeOut) {\r
1074 break;\r
1075 }\r
1076 }\r
1077 //\r
1078 // Check results\r
1079 //\r
b6763e03 1080 if (GotIt == 1) {\r
05fbd06d 1081 return EFI_SUCCESS;\r
1082 } else {\r
1083 return EFI_TIMEOUT;\r
1084 }\r
1085\r
1086}\r
1087\r
bcd70414 1088/**\r
05fbd06d 1089 Show keyboard status lights according to\r
1090 indicators in ConsoleIn.\r
1091\r
bcd70414 1092 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
1093 \r
b6763e03 1094 @return status of updating keyboard register\r
05fbd06d 1095\r
bcd70414 1096**/\r
1097EFI_STATUS\r
1098UpdateStatusLights (\r
1099 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1100 )\r
05fbd06d 1101{\r
1102 EFI_STATUS Status;\r
1103 UINT8 Command;\r
1104\r
1105 //\r
1106 // Send keyboard command\r
1107 //\r
1108 Status = KeyboardWrite (ConsoleIn, 0xed);\r
1109 if (EFI_ERROR (Status)) {\r
1110 return Status;\r
1111 }\r
1112\r
1113 KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1114\r
1115 //\r
1116 // Light configuration\r
1117 //\r
1118 Command = 0;\r
1119 if (ConsoleIn->CapsLock) {\r
1120 Command |= 4;\r
1121 }\r
1122\r
1123 if (ConsoleIn->NumLock) {\r
1124 Command |= 2;\r
1125 }\r
1126\r
1127 if (ConsoleIn->ScrollLock) {\r
1128 Command |= 1;\r
1129 }\r
1130\r
1131 Status = KeyboardWrite (ConsoleIn, Command);\r
1132\r
1133 if (EFI_ERROR (Status)) {\r
1134 return Status;\r
1135 }\r
1136\r
1137 KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1138 return Status;\r
1139}\r
1140\r
bcd70414 1141/**\r
c220787b 1142 Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec.\r
05fbd06d 1143\r
c220787b 1144 The function is always called in TPL_NOTIFY.\r
05fbd06d 1145\r
c220787b 1146 @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer\r
05fbd06d 1147\r
bcd70414 1148**/\r
c220787b 1149VOID\r
bcd70414 1150KeyGetchar (\r
1151 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1152 )\r
05fbd06d 1153{\r
c220787b
RN
1154 EFI_STATUS Status;\r
1155 UINT8 ScanCode;\r
1156 BOOLEAN Extended;\r
1157 UINTN Index;\r
1158 EFI_KEY_DATA KeyData;\r
1159 LIST_ENTRY *Link;\r
1160 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
05fbd06d 1161 //\r
1162 // 4 bytes most\r
1163 //\r
c220787b
RN
1164 UINT8 ScancodeArr[4];\r
1165 UINT32 ScancodeArrPos;\r
05fbd06d 1166 //\r
1167 // point to the current position in ScancodeArr\r
1168 //\r
1169\r
05fbd06d 1170 Extended = FALSE;\r
1171 ScancodeArrPos = 0;\r
c220787b 1172 \r
05fbd06d 1173 //\r
1174 // Check if there are enough bytes of scancode representing a single key\r
1175 // available in the buffer\r
1176 //\r
b6763e03 1177 while (TRUE) {\r
05fbd06d 1178\r
c220787b
RN
1179 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 1, ScancodeArr);\r
1180 ScancodeArrPos = 0;\r
05fbd06d 1181 if (EFI_ERROR (Status)) {\r
c220787b 1182 return ;\r
05fbd06d 1183 }\r
1184\r
1185 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {\r
1186 Extended = TRUE;\r
c220787b 1187 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 2, ScancodeArr);\r
05fbd06d 1188 ScancodeArrPos = 1;\r
1189 if (EFI_ERROR (Status)) {\r
c220787b 1190 return ;\r
05fbd06d 1191 }\r
1192 }\r
1193 //\r
1194 // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5\r
1195 // if present, ignore them\r
1196 //\r
1197 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {\r
1198\r
c220787b 1199 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 2, ScancodeArr);\r
05fbd06d 1200 ScancodeArrPos = 1;\r
1201\r
1202 if (EFI_ERROR (Status)) {\r
c220787b 1203 return ;\r
05fbd06d 1204 }\r
1205\r
c220787b 1206 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 3, ScancodeArr);\r
05fbd06d 1207 ScancodeArrPos = 2;\r
1208\r
1209 if (EFI_ERROR (Status)) {\r
c220787b 1210 return ;\r
05fbd06d 1211 }\r
1212\r
c220787b
RN
1213 PopScancodeBufHead (&ConsoleIn->ScancodeQueue, 3, ScancodeArr);\r
1214 return ;\r
05fbd06d 1215 }\r
1216 //\r
1217 // if we reach this position, scancodes for a key is in buffer now,pop them\r
1218 //\r
c220787b 1219 Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);\r
05fbd06d 1220 if (EFI_ERROR (Status)) {\r
c220787b 1221 return ;\r
05fbd06d 1222 }\r
1223 //\r
1224 // store the last available byte, this byte of scancode will be checked\r
1225 //\r
1226 ScanCode = ScancodeArr[ScancodeArrPos];\r
1227\r
1228 //\r
1229 // Check for special keys and update the driver state.\r
1230 //\r
1231 switch (ScanCode) {\r
1232\r
1233 case SCANCODE_CTRL_MAKE:\r
1234 ConsoleIn->Ctrl = TRUE;\r
1235 break;\r
1236\r
1237 case SCANCODE_CTRL_BREAK:\r
1238 ConsoleIn->Ctrl = FALSE;\r
1239 break;\r
1240\r
1241 case SCANCODE_ALT_MAKE:\r
1242 ConsoleIn->Alt = TRUE;\r
1243 break;\r
1244\r
1245 case SCANCODE_ALT_BREAK:\r
1246 ConsoleIn->Alt = FALSE;\r
1247 break;\r
1248\r
1249 case SCANCODE_LEFT_SHIFT_MAKE:\r
f3d1e940 1250 if (!Extended) {\r
1251 ConsoleIn->Shift = TRUE;\r
1252 ConsoleIn->LeftShift = TRUE;\r
1253 } \r
1254 break;\r
05fbd06d 1255 case SCANCODE_RIGHT_SHIFT_MAKE:\r
1256 if (!Extended) {\r
1257 ConsoleIn->Shift = TRUE;\r
f3d1e940 1258 ConsoleIn->RightShift = TRUE;\r
05fbd06d 1259 }\r
1260 break;\r
1261\r
1262 case SCANCODE_LEFT_SHIFT_BREAK:\r
f3d1e940 1263 if (!Extended) {\r
1264 ConsoleIn->Shift = FALSE;\r
1265 ConsoleIn->LeftShift = FALSE;\r
1266 } else {\r
1267 ConsoleIn->SysReq = FALSE;\r
1268 } \r
1269 break;\r
05fbd06d 1270 case SCANCODE_RIGHT_SHIFT_BREAK:\r
1271 if (!Extended) {\r
1272 ConsoleIn->Shift = FALSE;\r
f3d1e940 1273 ConsoleIn->RightShift = FALSE;\r
05fbd06d 1274 }\r
1275 break;\r
1276\r
f3d1e940 1277 case SCANCODE_LEFT_LOGO_MAKE:\r
1278 ConsoleIn->LeftLogo = TRUE;\r
1279 break; \r
1280 case SCANCODE_LEFT_LOGO_BREAK:\r
1281 ConsoleIn->LeftLogo = FALSE;\r
1282 break; \r
1283 case SCANCODE_RIGHT_LOGO_MAKE:\r
1284 ConsoleIn->RightLogo = TRUE;\r
1285 break;\r
1286 case SCANCODE_RIGHT_LOGO_BREAK:\r
1287 ConsoleIn->RightLogo = FALSE;\r
1288 break; \r
1289 case SCANCODE_MENU_MAKE:\r
1290 ConsoleIn->Menu = TRUE;\r
1291 break;\r
1292 case SCANCODE_MENU_BREAK:\r
1293 ConsoleIn->Menu = FALSE;\r
1294 break; \r
1295 case SCANCODE_SYS_REQ_MAKE:\r
1296 if (Extended) {\r
1297 ConsoleIn->SysReq = TRUE;\r
1298 }\r
05fbd06d 1299 case SCANCODE_CAPS_LOCK_MAKE:\r
1300 ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;\r
1301 UpdateStatusLights (ConsoleIn);\r
1302 break;\r
1303\r
1304 case SCANCODE_NUM_LOCK_MAKE:\r
1305 ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;\r
1306 UpdateStatusLights (ConsoleIn);\r
1307 break;\r
1308\r
1309 case SCANCODE_SCROLL_LOCK_MAKE:\r
1310 ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;\r
1311 UpdateStatusLights (ConsoleIn);\r
1312 break;\r
1313 }\r
1314 //\r
1315 // If this is a BREAK Key or above the valid range, ignore it\r
1316 //\r
1317 if (ScanCode >= SCANCODE_MAX_MAKE) {\r
1318 continue;\r
1319 } else {\r
1320 break;\r
1321 }\r
1322 }\r
c220787b 1323\r
05fbd06d 1324 //\r
c220787b 1325 // Handle Ctrl+Alt+Del hotkey\r
05fbd06d 1326 //\r
c220787b
RN
1327 if (ConsoleIn->Alt && ConsoleIn->Ctrl && ScanCode == SCANCODE_DELETE_MAKE) {\r
1328 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
05fbd06d 1329 }\r
c220787b
RN
1330\r
1331 KeyData.Key.ScanCode = SCAN_NULL;\r
1332 KeyData.Key.UnicodeChar = CHAR_NULL;\r
1333 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
1334 KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
1335\r
05fbd06d 1336 //\r
c220787b 1337 // Treat Numeric Key Pad "/" specially\r
05fbd06d 1338 //\r
c220787b
RN
1339 if (Extended && ScanCode == 0x35) {\r
1340 KeyData.Key.UnicodeChar = L'/';\r
1341 KeyData.Key.ScanCode = SCAN_NULL;\r
1342 } else {\r
1343 //\r
1344 // Convert Keyboard ScanCode into an EFI Key\r
1345 //\r
1346 for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {\r
1347 if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {\r
1348 KeyData.Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;\r
1349 KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\r
1350\r
1351 if (ConsoleIn->Shift && \r
1352 (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {\r
1353 KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;\r
1354 //\r
1355 // Need not return associated shift state if a class of printable characters that\r
1356 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
1357 //\r
f3d1e940 1358 ConsoleIn->LeftShift = FALSE;\r
1359 ConsoleIn->RightShift = FALSE;\r
1360 }\r
c220787b
RN
1361 //\r
1362 // alphabetic key is affected by CapsLock State\r
1363 //\r
1364 if (ConsoleIn->CapsLock) {\r
1365 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
1366 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A');\r
1367 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
1368 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a');\r
1369 }\r
1f771698 1370 }\r
c220787b 1371 break;\r
1f771698 1372 }\r
05fbd06d 1373 }\r
1374 }\r
1375\r
1376 //\r
1377 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'\r
1378 //\r
1379 if (ScanCode >= 0x47 && ScanCode <= 0x53) {\r
05fbd06d 1380 if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {\r
c220787b 1381 KeyData.Key.ScanCode = SCAN_NULL;\r
05fbd06d 1382 } else if (ScanCode != 0x4a && ScanCode != 0x4e) {\r
c220787b 1383 KeyData.Key.UnicodeChar = CHAR_NULL;\r
05fbd06d 1384 }\r
1385 }\r
1386 //\r
1387 // If the key can not be converted then just return.\r
1388 //\r
c220787b
RN
1389 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {\r
1390 return ;\r
05fbd06d 1391 }\r
1392\r
f3d1e940 1393 //\r
1394 // Save the Shift/Toggle state\r
1395 //\r
1396 if (ConsoleIn->Ctrl) {\r
c220787b 1397 KeyData.KeyState.KeyShiftState |= (Extended) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;\r
f3d1e940 1398 } \r
1399 if (ConsoleIn->Alt) { \r
c220787b 1400 KeyData.KeyState.KeyShiftState |= (Extended) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;\r
f3d1e940 1401 } \r
1402 if (ConsoleIn->LeftShift) { \r
c220787b 1403 KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
f3d1e940 1404 } \r
1405 if (ConsoleIn->RightShift) { \r
c220787b 1406 KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
f3d1e940 1407 } \r
1408 if (ConsoleIn->LeftLogo) { \r
c220787b 1409 KeyData.KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
f3d1e940 1410 } \r
1411 if (ConsoleIn->RightLogo) { \r
c220787b 1412 KeyData.KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
f3d1e940 1413 } \r
1414 if (ConsoleIn->Menu) { \r
c220787b 1415 KeyData.KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
f3d1e940 1416 } \r
1417 if (ConsoleIn->SysReq) { \r
c220787b 1418 KeyData.KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
f3d1e940 1419 } \r
1420 if (ConsoleIn->CapsLock) {\r
c220787b 1421 KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
f3d1e940 1422 }\r
1423 if (ConsoleIn->NumLock) {\r
c220787b 1424 KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
f3d1e940 1425 }\r
1426 if (ConsoleIn->ScrollLock) {\r
c220787b 1427 KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
f3d1e940 1428 }\r
1429\r
c220787b
RN
1430 //\r
1431 // Invoke notification functions if exist\r
1432 //\r
1433 for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {\r
1434 CurrentNotify = CR (\r
1435 Link, \r
1436 KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1437 NotifyEntry, \r
1438 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1439 );\r
1440 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { \r
1441 CurrentNotify->KeyNotificationFn (&KeyData);\r
1442 }\r
1443 }\r
1444 \r
1445 //\r
1446 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
1447 //\r
1448 if (ConsoleIn->Ctrl) {\r
1449 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
1450 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
1451 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
1452 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
1453 }\r
1454 }\r
1455\r
1456 PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);\r
05fbd06d 1457}\r
1458\r
bcd70414 1459/**\r
f713c4fe 1460 Perform 8042 controller and keyboard Initialization. \r
05fbd06d 1461 If ExtendedVerification is TRUE, do additional test for\r
1462 the keyboard interface\r
1463\r
bcd70414 1464 @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer\r
1465 @param ExtendedVerification - indicates a thorough initialization\r
05fbd06d 1466\r
bcd70414 1467 @retval EFI_DEVICE_ERROR Fail to init keyboard\r
1468 @retval EFI_SUCCESS Success to init keyboard\r
1469**/\r
1470EFI_STATUS\r
1471InitKeyboard (\r
1472 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1473 IN BOOLEAN ExtendedVerification\r
1474 )\r
05fbd06d 1475{\r
1476 EFI_STATUS Status;\r
1477 EFI_STATUS Status1;\r
1478 UINT8 CommandByte;\r
05fbd06d 1479 EFI_PS2_POLICY_PROTOCOL *Ps2Policy;\r
05f89b17 1480 UINT32 TryTime;\r
05fbd06d 1481\r
05f89b17 1482 Status = EFI_SUCCESS;\r
4fd730b3 1483 mEnableMouseInterface = TRUE;\r
05f89b17 1484 TryTime = 0;\r
05fbd06d 1485\r
1486 //\r
1487 // Get Ps2 policy to set this\r
1488 //\r
05f89b17
LG
1489 gBS->LocateProtocol (\r
1490 &gEfiPs2PolicyProtocolGuid,\r
1491 NULL,\r
1492 (VOID **) &Ps2Policy\r
1493 );\r
05fbd06d 1494\r
1495 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1496 EFI_PROGRESS_CODE,\r
1497 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,\r
1498 ConsoleIn->DevicePath\r
1499 );\r
1500\r
1501 //\r
1502 // Perform a read to cleanup the Status Register's\r
05f89b17 1503 // output buffer full bits within MAX TRY times\r
05fbd06d 1504 //\r
05f89b17 1505 while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {\r
05fbd06d 1506 Status = KeyboardRead (ConsoleIn, &CommandByte);\r
05f89b17
LG
1507 TryTime ++;\r
1508 }\r
1509 //\r
1510 // Exceed the max try times. The device may be error.\r
1511 //\r
1512 if (TryTime == KEYBOARD_MAX_TRY) {\r
1513 Status = EFI_DEVICE_ERROR;\r
1514 goto Done;\r
05fbd06d 1515 }\r
1516 //\r
1517 // We should disable mouse interface during the initialization process\r
1518 // since mouse device output could block keyboard device output in the\r
1519 // 60H port of 8042 controller.\r
1520 //\r
1521 // So if we are not initializing 8042 controller for the\r
1522 // first time, we have to remember the previous mouse interface\r
1523 // enabling state\r
1524 //\r
1525 // Test the system flag in to determine whether this is the first\r
1526 // time initialization\r
1527 //\r
f713c4fe 1528 if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {\r
05fbd06d 1529 //\r
1530 // 8042 controller is already setup (by myself or by mouse driver):\r
1531 // See whether mouse interface is already enabled\r
1532 // which determines whether we should enable it later\r
1533 //\r
1534 //\r
1535 // Read the command byte of 8042 controller\r
1536 //\r
b6763e03 1537 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);\r
05fbd06d 1538 if (EFI_ERROR (Status)) {\r
1539 KeyboardError (ConsoleIn, L"\n\r");\r
1540 goto Done;\r
1541 }\r
1542\r
1543 Status = KeyboardRead (ConsoleIn, &CommandByte);\r
1544 if (EFI_ERROR (Status)) {\r
1545 KeyboardError (ConsoleIn, L"\n\r");\r
1546 goto Done;\r
1547 }\r
1548 //\r
1549 // Test the mouse enabling bit\r
1550 //\r
f713c4fe 1551 if ((CommandByte & 0x20) != 0) {\r
4fd730b3 1552 mEnableMouseInterface = FALSE;\r
05fbd06d 1553 } else {\r
4fd730b3 1554 mEnableMouseInterface = TRUE;\r
05fbd06d 1555 }\r
1556\r
1557 } else {\r
1558 //\r
1559 // 8042 controller is not setup yet:\r
1560 // 8042 controller selftest;\r
1561 // Don't enable mouse interface later.\r
1562 //\r
1563 //\r
1564 // Disable keyboard and mouse interfaces\r
1565 //\r
b6763e03 1566 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);\r
05fbd06d 1567 if (EFI_ERROR (Status)) {\r
1568 KeyboardError (ConsoleIn, L"\n\r");\r
1569 goto Done;\r
1570 }\r
1571\r
b6763e03 1572 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);\r
05fbd06d 1573 if (EFI_ERROR (Status)) {\r
1574 KeyboardError (ConsoleIn, L"\n\r");\r
1575 goto Done;\r
1576 }\r
1577\r
1578 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1579 EFI_PROGRESS_CODE,\r
1580 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,\r
1581 ConsoleIn->DevicePath\r
1582 );\r
1583 //\r
1584 // 8042 Controller Self Test\r
1585 //\r
b6763e03 1586 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);\r
05fbd06d 1587 if (EFI_ERROR (Status)) {\r
1588 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1589 goto Done;\r
1590 }\r
1591\r
1592 Status = KeyboardWaitForValue (ConsoleIn, 0x55);\r
1593 if (EFI_ERROR (Status)) {\r
1594 KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");\r
1595 goto Done;\r
1596 }\r
1597 //\r
1598 // Don't enable mouse interface later\r
1599 //\r
4fd730b3 1600 mEnableMouseInterface = FALSE;\r
05fbd06d 1601\r
1602 }\r
1603\r
1604 if (Ps2Policy != NULL) {\r
1605 Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);\r
1606 }\r
1607 //\r
1608 // Write 8042 Command Byte, set System Flag\r
1609 // While at the same time:\r
1610 // 1. disable mouse interface,\r
1611 // 2. enable kbd interface,\r
1612 // 3. enable PC/XT kbd translation mode\r
1613 // 4. enable mouse and kbd interrupts\r
1614 //\r
1615 // ( Command Byte bits:\r
1616 // 7: Reserved\r
1617 // 6: PC/XT translation mode\r
1618 // 5: Disable Auxiliary device interface\r
1619 // 4: Disable keyboard interface\r
1620 // 3: Reserved\r
1621 // 2: System Flag\r
1622 // 1: Enable Auxiliary device interrupt\r
1623 // 0: Enable Keyboard interrupt )\r
1624 //\r
b6763e03 1625 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);\r
05fbd06d 1626 if (EFI_ERROR (Status)) {\r
1627 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1628 goto Done;\r
1629 }\r
1630\r
1631 Status = KeyboardWrite (ConsoleIn, 0x67);\r
1632 if (EFI_ERROR (Status)) {\r
1633 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1634 goto Done;\r
1635 }\r
1636\r
1637 //\r
1638 // Clear Memory Scancode Buffer\r
1639 //\r
c220787b
RN
1640 ConsoleIn->ScancodeQueue.Head = 0;\r
1641 ConsoleIn->ScancodeQueue.Tail = 0;\r
1642 ConsoleIn->EfiKeyQueue.Head = 0;\r
1643 ConsoleIn->EfiKeyQueue.Tail = 0;\r
05fbd06d 1644\r
1645 //\r
1646 // Reset the status indicators\r
1647 //\r
1648 ConsoleIn->Ctrl = FALSE;\r
1649 ConsoleIn->Alt = FALSE;\r
1650 ConsoleIn->Shift = FALSE;\r
1651 ConsoleIn->CapsLock = FALSE;\r
1652 ConsoleIn->NumLock = FALSE;\r
1653 ConsoleIn->ScrollLock = FALSE;\r
f3d1e940 1654 ConsoleIn->LeftShift = FALSE;\r
1655 ConsoleIn->RightShift = FALSE;\r
1656 ConsoleIn->LeftLogo = FALSE;\r
1657 ConsoleIn->RightLogo = FALSE;\r
1658 ConsoleIn->Menu = FALSE;\r
1659 ConsoleIn->SysReq = FALSE; \r
05fbd06d 1660\r
1661 //\r
1662 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
1663 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected\r
1664 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,\r
1665 // and normally during booting an OS, it's skipped.\r
1666 //\r
1667 if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {\r
1668 //\r
1669 // Additional verifications for keyboard interface\r
1670 //\r
1671 //\r
1672 // Keyboard Interface Test\r
1673 //\r
b6763e03 1674 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);\r
05fbd06d 1675 if (EFI_ERROR (Status)) {\r
1676 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1677 goto Done;\r
1678 }\r
1679\r
1680 Status = KeyboardWaitForValue (ConsoleIn, 0x00);\r
1681 if (EFI_ERROR (Status)) {\r
1682 KeyboardError (\r
1683 ConsoleIn,\r
1684 L"Some specific value not aquired from 8042 controller!\n\r"\r
1685 );\r
1686 goto Done;\r
1687 }\r
1688 //\r
1689 // Keyboard reset with a BAT(Basic Assurance Test)\r
1690 //\r
b6763e03 1691 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);\r
05fbd06d 1692 if (EFI_ERROR (Status)) {\r
1693 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1694 goto Done;\r
1695 }\r
1696\r
b6763e03 1697 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);\r
05fbd06d 1698 if (EFI_ERROR (Status)) {\r
1699 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1700 goto Done;\r
1701 }\r
1702 //\r
1703 // wait for BAT completion code\r
1704 //\r
1705 mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT;\r
1706\r
b6763e03 1707 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);\r
05fbd06d 1708 if (EFI_ERROR (Status)) {\r
1709 KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");\r
1710 goto Done;\r
1711 }\r
1712\r
1713 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
1714\r
1715 //\r
1716 // Set Keyboard to use Scan Code Set 2\r
1717 //\r
b6763e03 1718 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);\r
05fbd06d 1719 if (EFI_ERROR (Status)) {\r
1720 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1721 goto Done;\r
1722 }\r
1723\r
b6763e03 1724 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);\r
05fbd06d 1725 if (EFI_ERROR (Status)) {\r
1726 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1727 goto Done;\r
1728 }\r
1729\r
1730 Status = KeyboardWrite (ConsoleIn, 0x02);\r
1731 if (EFI_ERROR (Status)) {\r
1732 KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");\r
1733 goto Done;\r
1734 }\r
1735\r
b6763e03 1736 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);\r
05fbd06d 1737 if (EFI_ERROR (Status)) {\r
1738 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1739 goto Done;\r
1740 }\r
1741\r
1742 //\r
1743 // Clear Keyboard Scancode Buffer\r
1744 //\r
b6763e03 1745 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);\r
05fbd06d 1746 if (EFI_ERROR (Status)) {\r
1747 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1748 goto Done;\r
1749 }\r
1750\r
b6763e03 1751 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);\r
05fbd06d 1752 if (EFI_ERROR (Status)) {\r
1753 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1754 goto Done;\r
1755 }\r
1756 //\r
1757 if (Ps2Policy != NULL) {\r
1758 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {\r
1759 ConsoleIn->CapsLock = TRUE;\r
1760 }\r
1761\r
1762 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {\r
1763 ConsoleIn->NumLock = TRUE;\r
1764 }\r
1765\r
1766 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {\r
1767 ConsoleIn->ScrollLock = TRUE;\r
1768 }\r
1769 }\r
1770 //\r
1771 // Update Keyboard Lights\r
1772 //\r
1773 Status = UpdateStatusLights (ConsoleIn);\r
1774 if (EFI_ERROR (Status)) {\r
1775 KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");\r
1776 goto Done;\r
1777 }\r
1778 }\r
1779 //\r
1780 // At last, we can now enable the mouse interface if appropriate\r
1781 //\r
1782Done:\r
1783\r
4fd730b3 1784 if (mEnableMouseInterface) {\r
05fbd06d 1785 //\r
1786 // Enable mouse interface\r
1787 //\r
b6763e03 1788 Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);\r
05fbd06d 1789 if (EFI_ERROR (Status1)) {\r
1790 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1791 return EFI_DEVICE_ERROR;\r
1792 }\r
1793 }\r
1794\r
1795 if (!EFI_ERROR (Status)) {\r
1796 return EFI_SUCCESS;\r
1797 } else {\r
1798 return EFI_DEVICE_ERROR;\r
1799 }\r
1800\r
1801}\r
1802\r
bcd70414 1803/**\r
f713c4fe 1804 Disable the keyboard interface of the 8042 controller.\r
05fbd06d 1805\r
f713c4fe 1806 @param ConsoleIn The device instance\r
05fbd06d 1807\r
bcd70414 1808 @return status of issuing disable command\r
05fbd06d 1809\r
bcd70414 1810**/\r
1811EFI_STATUS\r
1812DisableKeyboard (\r
1813 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1814 )\r
05fbd06d 1815{\r
1816 EFI_STATUS Status;\r
1817\r
1818 //\r
1819 // Disable keyboard interface\r
1820 //\r
b6763e03 1821 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);\r
05fbd06d 1822 if (EFI_ERROR (Status)) {\r
1823 KeyboardError (ConsoleIn, L"\n\r");\r
1824 return EFI_DEVICE_ERROR;\r
1825 }\r
1826\r
1827 return Status;\r
1828}\r
1829\r
1830/**\r
1831 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command\r
1832 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device\r
1833 should not be in system.\r
1834\r
fdb05fa3 1835 @param[in] ConsoleIn Keyboard Private Data Structure\r
05fbd06d 1836\r
f3d1e940 1837 @retval TRUE Keyboard in System.\r
1838 @retval FALSE Keyboard not in System.\r
05fbd06d 1839**/\r
1840BOOLEAN\r
1841EFIAPI\r
1842CheckKeyboardConnect (\r
1843 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1844 )\r
1845{\r
1846 EFI_STATUS Status;\r
1847 UINTN WaitForValueTimeOutBcakup;\r
1848\r
1849 Status = EFI_SUCCESS;\r
1850 //\r
1851 // enable keyboard itself and wait for its ack\r
1852 // If can't receive ack, Keyboard should not be connected.\r
1853 //\r
1854 Status = KeyboardWrite (\r
1855 ConsoleIn,\r
1856 KEYBOARD_KBEN\r
1857 );\r
1858\r
1859 if (EFI_ERROR (Status)) {\r
1860 return FALSE;\r
1861 }\r
1862 //\r
1863 // wait for 1s\r
1864 //\r
1865 WaitForValueTimeOutBcakup = mWaitForValueTimeOut;\r
1866 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
1867 Status = KeyboardWaitForValue (\r
1868 ConsoleIn,\r
1869 KEYBOARD_CMDECHO_ACK\r
1870 );\r
1871 mWaitForValueTimeOut = WaitForValueTimeOutBcakup;\r
1872\r
1873 if (EFI_ERROR (Status)) {\r
1874 return FALSE;\r
1875 }\r
1876\r
1877 return TRUE;\r
1878}\r
bcd70414 1879\r