]> git.proxmox.com Git - mirror_edk2.git/blob - Nt32Pkg/WinNtGopDxe/WinNtGopInput.c
UefiCpuPkg: Remove double \r
[mirror_edk2.git] / Nt32Pkg / WinNtGopDxe / WinNtGopInput.c
1 /** @file
2
3 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 Module Name:
7
8 WinNtGopInput.c
9
10 Abstract:
11
12 This file produces the Simple Text In for an Gop window.
13
14 This stuff is linked at the hip to the Window, since the window
15 processing is done in a thread kicked off in WinNtGopImplementation.c
16
17 Since the window information is processed in an other thread we need
18 a keyboard Queue to pass data about. The Simple Text In code just
19 takes data off the Queue. The WinProc message loop takes keyboard input
20 and places it in the Queue.
21
22
23 **/
24
25
26 #include "WinNtGop.h"
27
28
29 /**
30 TODO: Add function description
31
32 @param Private TODO: add argument description
33
34 @retval EFI_SUCCESS TODO: Add description for return value
35
36 **/
37 EFI_STATUS
38 GopPrivateCreateQ (
39 IN GOP_PRIVATE_DATA *Private,
40 IN GOP_QUEUE_FIXED *Queue
41 )
42 {
43 Private->WinNtThunk->InitializeCriticalSection (&Queue->Cs);
44 Queue->Front = 0;
45 Queue->Rear = 0;
46 return EFI_SUCCESS;
47 }
48
49
50 /**
51 TODO: Add function description
52
53 @param Private TODO: add argument description
54
55 @retval EFI_SUCCESS TODO: Add description for return value
56
57 **/
58 EFI_STATUS
59 GopPrivateDestroyQ (
60 IN GOP_PRIVATE_DATA *Private,
61 IN GOP_QUEUE_FIXED *Queue
62 )
63 {
64 Queue->Front = 0;
65 Queue->Rear = 0;
66 Private->WinNtThunk->DeleteCriticalSection (&Queue->Cs);
67 return EFI_SUCCESS;
68 }
69
70
71 /**
72 TODO: Add function description
73
74 @param Private TODO: add argument description
75 @param Key TODO: add argument description
76
77 @retval EFI_NOT_READY TODO: Add description for return value
78 @retval EFI_SUCCESS TODO: Add description for return value
79
80 **/
81 EFI_STATUS
82 GopPrivateAddQ (
83 IN GOP_PRIVATE_DATA *Private,
84 IN GOP_QUEUE_FIXED *Queue,
85 IN EFI_KEY_DATA *KeyData
86 )
87 {
88 Private->WinNtThunk->EnterCriticalSection (&Queue->Cs);
89
90 if ((Queue->Rear + 1) % MAX_Q == Queue->Front) {
91 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs);
92 return EFI_NOT_READY;
93 }
94
95 CopyMem (&Queue->Q[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));
96 Queue->Rear = (Queue->Rear + 1) % MAX_Q;
97
98 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs);
99 return EFI_SUCCESS;
100 }
101
102
103 /**
104 TODO: Add function description
105
106 @param Private TODO: add argument description
107 @param Key TODO: add argument description
108
109 @retval EFI_NOT_READY TODO: Add description for return value
110 @retval EFI_SUCCESS TODO: Add description for return value
111
112 **/
113 EFI_STATUS
114 GopPrivateDeleteQ (
115 IN GOP_PRIVATE_DATA *Private,
116 IN GOP_QUEUE_FIXED *Queue,
117 OUT EFI_KEY_DATA *Key
118 )
119 {
120 Private->WinNtThunk->EnterCriticalSection (&Queue->Cs);
121
122 if (Queue->Front == Queue->Rear) {
123 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs);
124 return EFI_NOT_READY;
125 }
126
127 CopyMem (Key, &Queue->Q[Queue->Front], sizeof (EFI_KEY_DATA));
128 Queue->Front = (Queue->Front + 1) % MAX_Q;
129
130 if (Key->Key.ScanCode == SCAN_NULL && Key->Key.UnicodeChar == CHAR_NULL) {
131 if (!Private->IsPartialKeySupport) {
132 //
133 // If partial keystrok is not enabled, don't return the partial keystroke.
134 //
135 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs);
136 ZeroMem (Key, sizeof (EFI_KEY_DATA));
137 return EFI_NOT_READY;
138 }
139 }
140 Private->WinNtThunk->LeaveCriticalSection (&Queue->Cs);
141 return EFI_SUCCESS;
142 }
143
144
145 /**
146 TODO: Add function description
147
148 @param Private TODO: add argument description
149
150 @retval EFI_NOT_READY TODO: Add description for return value
151 @retval EFI_SUCCESS TODO: Add description for return value
152
153 **/
154 EFI_STATUS
155 GopPrivateCheckQ (
156 IN GOP_QUEUE_FIXED *Queue
157 )
158 {
159 if (Queue->Front == Queue->Rear) {
160 return EFI_NOT_READY;
161 }
162
163 return EFI_SUCCESS;
164 }
165
166 BOOLEAN
167 GopPrivateIsKeyRegistered (
168 IN EFI_KEY_DATA *RegsiteredData,
169 IN EFI_KEY_DATA *InputData
170 )
171 /*++
172
173 Routine Description:
174
175 Arguments:
176
177 RegsiteredData - A pointer to a buffer that is filled in with the keystroke
178 state data for the key that was registered.
179 InputData - A pointer to a buffer that is filled in with the keystroke
180 state data for the key that was pressed.
181
182 Returns:
183 TRUE - Key be pressed matches a registered key.
184 FLASE - Match failed.
185
186 --*/
187 {
188 ASSERT (RegsiteredData != NULL && InputData != NULL);
189
190 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
191 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
192 return FALSE;
193 }
194
195 //
196 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
197 //
198 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
199 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
200 return FALSE;
201 }
202 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
203 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
204 return FALSE;
205 }
206
207 return TRUE;
208
209 }
210
211
212 VOID
213 GopPrivateInvokeRegisteredFunction (
214 IN GOP_PRIVATE_DATA *Private,
215 IN EFI_KEY_DATA *KeyData
216 )
217 /*++
218
219 Routine Description:
220
221 This function updates the status light of NumLock, ScrollLock and CapsLock.
222
223 Arguments:
224
225 Private - The private structure of WinNt Gop device.
226 KeyData - A pointer to a buffer that is filled in with the keystroke
227 state data for the key that was pressed.
228
229 Returns:
230
231 EFI_SUCCESS - The status light is updated successfully.
232
233 --*/
234 {
235 LIST_ENTRY *Link;
236 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify;
237
238 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
239 CurrentNotify = CR (
240 Link,
241 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
242 NotifyEntry,
243 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
244 );
245 if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
246 CurrentNotify->KeyNotificationFn (KeyData);
247 }
248 }
249 }
250
251 VOID
252 WinNtGopSimpleTextInTimerHandler (
253 IN EFI_EVENT Event,
254 IN VOID *Context
255 )
256 {
257 GOP_PRIVATE_DATA *Private;
258 EFI_KEY_DATA KeyData;
259
260 Private = (GOP_PRIVATE_DATA *)Context;
261 while (GopPrivateDeleteQ (Private, &Private->QueueForNotify, &KeyData) == EFI_SUCCESS) {
262 GopPrivateInvokeRegisteredFunction (Private, &KeyData);
263 }
264 }
265
266 /**
267 Initialize the key state.
268
269 @param Private The GOP_PRIVATE_DATA instance.
270 @param KeyState A pointer to receive the key state information.
271 **/
272 VOID
273 InitializeKeyState (
274 IN GOP_PRIVATE_DATA *Private,
275 IN EFI_KEY_STATE *KeyState
276 )
277 {
278 KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID;
279 KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID;
280
281 //
282 // Record Key shift state and toggle state
283 //
284 if (Private->LeftCtrl) {
285 KeyState->KeyShiftState |= EFI_LEFT_CONTROL_PRESSED;
286 }
287 if (Private->RightCtrl) {
288 KeyState->KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED;
289 }
290 if (Private->LeftAlt) {
291 KeyState->KeyShiftState |= EFI_LEFT_ALT_PRESSED;
292 }
293 if (Private->RightAlt) {
294 KeyState->KeyShiftState |= EFI_RIGHT_ALT_PRESSED;
295 }
296 if (Private->LeftShift) {
297 KeyState->KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
298 }
299 if (Private->RightShift) {
300 KeyState->KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
301 }
302 if (Private->LeftLogo) {
303 KeyState->KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
304 }
305 if (Private->RightLogo) {
306 KeyState->KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
307 }
308 if (Private->Menu) {
309 KeyState->KeyShiftState |= EFI_MENU_KEY_PRESSED;
310 }
311 if (Private->SysReq) {
312 KeyState->KeyShiftState |= EFI_SYS_REQ_PRESSED;
313 }
314 if (Private->CapsLock) {
315 KeyState->KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
316 }
317 if (Private->NumLock) {
318 KeyState->KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
319 }
320 if (Private->ScrollLock) {
321 KeyState->KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
322 }
323 if (Private->IsPartialKeySupport) {
324 KeyState->KeyToggleState |= EFI_KEY_STATE_EXPOSED;
325 }
326 }
327
328 /**
329 TODO: Add function description
330
331 @param Private TODO: add argument description
332 @param Key TODO: add argument description
333
334 @retval EFI_NOT_READY TODO: Add description for return value
335 @retval EFI_SUCCESS TODO: Add description for return value
336
337 **/
338 EFI_STATUS
339 GopPrivateAddKey (
340 IN GOP_PRIVATE_DATA *Private,
341 IN EFI_INPUT_KEY Key
342 )
343 {
344 EFI_KEY_DATA KeyData;
345
346 KeyData.Key = Key;
347 InitializeKeyState (Private, &KeyData.KeyState);
348
349 //
350 // Convert Ctrl+[1-26] to Ctrl+[A-Z]
351 //
352 if ((Private->LeftCtrl || Private->RightCtrl) &&
353 (KeyData.Key.UnicodeChar >= 1) && (KeyData.Key.UnicodeChar <= 26)
354 ) {
355 if ((Private->LeftShift || Private->RightShift) == Private->CapsLock) {
356 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'a' - 1);
357 } else {
358 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar + L'A' - 1);
359 }
360 }
361
362 //
363 // Unmask the Shift bit for printable char
364 //
365 if (((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) ||
366 ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z'))
367 ) {
368 KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
369 }
370
371 GopPrivateAddQ (Private, &Private->QueueForNotify, &KeyData);
372
373 GopPrivateAddQ (Private, &Private->QueueForRead, &KeyData);
374
375 return EFI_SUCCESS;
376 }
377
378 EFI_STATUS
379 GopPrivateUpdateStatusLight (
380 IN GOP_PRIVATE_DATA *Private
381 )
382 /*++
383
384 Routine Description:
385
386 This function updates the status light of NumLock, ScrollLock and CapsLock.
387
388 Arguments:
389
390 Private - The private structure of WinNt console In/Out.
391
392 Returns:
393
394 EFI_SUCCESS - The status light is updated successfully.
395
396 --*/
397 {
398 //
399 // BUGBUG:Only SendInput/keybd_event function can toggle
400 // NumLock, CapsLock and ScrollLock keys.
401 // Neither of these functions is included in EFI_WIN_NT_THUNK_PROTOCOL.
402 // Thus, return immediately without operation.
403 //
404 return EFI_SUCCESS;
405
406 }
407
408
409 EFI_STATUS
410 GopPrivateResetWorker (
411 IN GOP_PRIVATE_DATA *Private
412 )
413 /*++
414
415 Routine Description:
416
417 This function is a worker function for SimpleTextIn/SimpleTextInEx.Reset().
418
419 Arguments:
420
421 Private - WinNT GOP private structure
422
423 Returns:
424
425 EFI_SUCCESS - Reset successfully
426
427 --*/
428 {
429 EFI_KEY_DATA KeyData;
430 EFI_TPL OldTpl;
431
432 //
433 // Enter critical section
434 //
435 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
436
437 //
438 // A reset is draining the Queue
439 //
440 while (GopPrivateDeleteQ (Private, &Private->QueueForRead, &KeyData) == EFI_SUCCESS)
441 ;
442 while (GopPrivateDeleteQ (Private, &Private->QueueForNotify, &KeyData) == EFI_SUCCESS)
443 ;
444
445 Private->LeftShift = FALSE;
446 Private->RightShift = FALSE;
447 Private->LeftAlt = FALSE;
448 Private->RightAlt = FALSE;
449 Private->LeftCtrl = FALSE;
450 Private->RightCtrl = FALSE;
451 Private->LeftLogo = FALSE;
452 Private->RightLogo = FALSE;
453 Private->Menu = FALSE;
454 Private->SysReq = FALSE;
455
456 Private->CapsLock = FALSE;
457 Private->NumLock = FALSE;
458 Private->ScrollLock = FALSE;
459 Private->IsPartialKeySupport = FALSE;
460
461 Private->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
462 Private->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
463
464 //
465 // Leave critical section and return
466 //
467 gBS->RestoreTPL (OldTpl);
468
469 return EFI_SUCCESS;
470 }
471
472 EFI_STATUS
473 GopPrivateReadKeyStrokeWorker (
474 IN GOP_PRIVATE_DATA *Private,
475 OUT EFI_KEY_DATA *KeyData
476 )
477 /*++
478
479 Routine Description:
480 Reads the next keystroke from the input device. The WaitForKey Event can
481 be used to test for existance of a keystroke via WaitForEvent () call.
482
483 Arguments:
484 Private - The private structure of WinNt Gop device.
485 KeyData - A pointer to a buffer that is filled in with the keystroke
486 state data for the key that was pressed.
487
488 Returns:
489 EFI_SUCCESS - The keystroke information was returned.
490 EFI_NOT_READY - There was no keystroke data availiable.
491 EFI_DEVICE_ERROR - The keystroke information was not returned due to
492 hardware errors.
493 EFI_INVALID_PARAMETER - KeyData is NULL.
494
495 --*/
496 {
497 EFI_STATUS Status;
498 EFI_TPL OldTpl;
499
500 if (KeyData == NULL) {
501 return EFI_INVALID_PARAMETER;
502 }
503
504 //
505 // Enter critical section
506 //
507 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
508
509 //
510 // Call hot key callback before telling caller there is a key available
511 //
512 WinNtGopSimpleTextInTimerHandler (NULL, Private);
513
514 ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
515 InitializeKeyState (Private, &KeyData->KeyState);
516
517 Status = GopPrivateCheckQ (&Private->QueueForRead);
518 if (!EFI_ERROR (Status)) {
519 //
520 // If a Key press exists try and read it.
521 //
522 Status = GopPrivateDeleteQ (Private, &Private->QueueForRead, KeyData);
523 if (!EFI_ERROR (Status)) {
524 //
525 // If partial keystroke is not enabled, check whether it is value key. If not return
526 // EFI_NOT_READY.
527 //
528 if (!Private->IsPartialKeySupport) {
529 if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) {
530 Status = EFI_NOT_READY;
531 }
532 }
533 }
534 }
535
536 //
537 // Leave critical section and return
538 //
539 gBS->RestoreTPL (OldTpl);
540
541 return Status;
542
543 }
544
545
546 //
547 // Simple Text In implementation.
548 //
549
550
551 /**
552 TODO: Add function description
553
554 @param This TODO: add argument description
555 @param ExtendedVerification TODO: add argument description
556
557 @retval EFI_SUCCESS TODO: Add description for return value
558
559 **/
560 EFI_STATUS
561 EFIAPI
562 WinNtGopSimpleTextInReset (
563 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
564 IN BOOLEAN ExtendedVerification
565 )
566 {
567 GOP_PRIVATE_DATA *Private;
568
569 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This);
570
571 return GopPrivateResetWorker (Private);
572 }
573
574
575 /**
576 TODO: Add function description
577
578 @param This TODO: add argument description
579 @param Key TODO: add argument description
580
581 @return TODO: add return values
582
583 **/
584 EFI_STATUS
585 EFIAPI
586 WinNtGopSimpleTextInReadKeyStroke (
587 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
588 OUT EFI_INPUT_KEY *Key
589 )
590 {
591 GOP_PRIVATE_DATA *Private;
592 EFI_STATUS Status;
593 EFI_KEY_DATA KeyData;
594
595 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This);
596 //
597 // Considering if the partial keystroke is enabled, there maybe a partial
598 // keystroke in the queue, so here skip the partial keystroke and get the
599 // next key from the queue
600 //
601 while (1) {
602 Status = GopPrivateReadKeyStrokeWorker (Private, &KeyData);
603 if (EFI_ERROR (Status)) {
604 return Status;
605 }
606 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
607 continue;
608 }
609 //
610 // Convert Ctrl+[A-Z] to Ctrl+[1-26]
611 //
612 if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
613 if ((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) {
614 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);
615 } else if ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) {
616 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);
617 }
618 }
619 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
620 return EFI_SUCCESS;
621 }
622 }
623
624
625 /**
626 TODO: Add function description
627
628 @param Event TODO: add argument description
629 @param Context TODO: add argument description
630
631 @return TODO: add return values
632
633 **/
634 VOID
635 EFIAPI
636 WinNtGopSimpleTextInWaitForKey (
637 IN EFI_EVENT Event,
638 IN VOID *Context
639 )
640 {
641 GOP_PRIVATE_DATA *Private;
642 EFI_STATUS Status;
643 EFI_TPL OldTpl;
644 EFI_KEY_DATA KeyData;
645
646 Private = (GOP_PRIVATE_DATA *) Context;
647
648 //
649 // Enter critical section
650 //
651 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
652
653 //
654 // Call hot key callback before telling caller there is a key available
655 //
656 WinNtGopSimpleTextInTimerHandler (NULL, Private);
657
658 //
659 // WaitforKey doesn't suppor the partial key.
660 // Considering if the partial keystroke is enabled, there maybe a partial
661 // keystroke in the queue, so here skip the partial keystroke and get the
662 // next key from the queue
663 //
664 while (1) {
665 Status = GopPrivateCheckQ (&Private->QueueForRead);
666 if (!EFI_ERROR (Status)) {
667 //
668 // If a there is a key in the queue and it is not partial keystroke, signal event.
669 //
670 if (Private->QueueForRead.Q[Private->QueueForRead.Front].Key.ScanCode == SCAN_NULL &&
671 Private->QueueForRead.Q[Private->QueueForRead.Front].Key.UnicodeChar == CHAR_NULL) {
672 GopPrivateDeleteQ (Private,&Private->QueueForRead,&KeyData);
673 continue;
674 }
675 gBS->SignalEvent (Event);
676 } else {
677 //
678 // We need to sleep or NT will schedule this thread with such high
679 // priority that WinProc thread will never run and we will not see
680 // keyboard input. This Sleep makes the syste run 10x faster, so don't
681 // remove it.
682 //
683 Private->WinNtThunk->Sleep (1);
684 }
685 break;
686 }
687
688 //
689 // Leave critical section and return
690 //
691 gBS->RestoreTPL (OldTpl);
692 }
693
694 //
695 // Simple Text Input Ex protocol functions
696 //
697
698 EFI_STATUS
699 EFIAPI
700 WinNtGopSimpleTextInExResetEx (
701 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
702 IN BOOLEAN ExtendedVerification
703 )
704 /*++
705
706 Routine Description:
707 Reset the input device and optionaly run diagnostics
708
709 Arguments:
710 This - Protocol instance pointer.
711 ExtendedVerification - Driver may perform diagnostics on reset.
712
713 Returns:
714 EFI_SUCCESS - The device was reset.
715
716 --*/
717 {
718 GOP_PRIVATE_DATA *Private;
719
720 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
721
722 return GopPrivateResetWorker (Private);
723 }
724
725 EFI_STATUS
726 EFIAPI
727 WinNtGopSimpleTextInExReadKeyStrokeEx (
728 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
729 OUT EFI_KEY_DATA *KeyData
730 )
731 /*++
732
733 Routine Description:
734 Reads the next keystroke from the input device. The WaitForKey Event can
735 be used to test for existance of a keystroke via WaitForEvent () call.
736
737 Arguments:
738 This - Protocol instance pointer.
739 KeyData - A pointer to a buffer that is filled in with the keystroke
740 state data for the key that was pressed.
741
742 Returns:
743 EFI_SUCCESS - The keystroke information was returned.
744 EFI_NOT_READY - There was no keystroke data availiable.
745 EFI_DEVICE_ERROR - The keystroke information was not returned due to
746 hardware errors.
747 EFI_INVALID_PARAMETER - KeyData is NULL.
748
749 --*/
750 {
751 GOP_PRIVATE_DATA *Private;
752
753 if (KeyData == NULL) {
754 return EFI_INVALID_PARAMETER;
755 }
756
757 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
758
759 return GopPrivateReadKeyStrokeWorker (Private, KeyData);
760
761 }
762
763 EFI_STATUS
764 EFIAPI
765 WinNtGopSimpleTextInExSetState (
766 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
767 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
768 )
769 /*++
770
771 Routine Description:
772 Set certain state for the input device.
773
774 Arguments:
775 This - Protocol instance pointer.
776 KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the
777 state for the input device.
778
779 Returns:
780 EFI_SUCCESS - The device state was set successfully.
781 EFI_DEVICE_ERROR - The device is not functioning correctly and could
782 not have the setting adjusted.
783 EFI_UNSUPPORTED - The device does not have the ability to set its state.
784 EFI_INVALID_PARAMETER - KeyToggleState is NULL.
785
786 --*/
787 {
788 EFI_STATUS Status;
789 GOP_PRIVATE_DATA *Private;
790
791 if (KeyToggleState == NULL) {
792 return EFI_INVALID_PARAMETER;
793 }
794
795 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
796
797 if (((Private->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||
798 ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {
799 return EFI_UNSUPPORTED;
800 }
801
802 Private->ScrollLock = FALSE;
803 Private->NumLock = FALSE;
804 Private->CapsLock = FALSE;
805 Private->IsPartialKeySupport = FALSE;
806
807 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
808 Private->ScrollLock = TRUE;
809 }
810 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
811 Private->NumLock = TRUE;
812 }
813 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
814 Private->CapsLock = TRUE;
815 }
816 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {
817 Private->IsPartialKeySupport = TRUE;
818 }
819
820 Status = GopPrivateUpdateStatusLight (Private);
821 if (EFI_ERROR (Status)) {
822 return EFI_DEVICE_ERROR;
823 }
824
825 Private->KeyState.KeyToggleState = *KeyToggleState;
826 return EFI_SUCCESS;
827
828 }
829
830 EFI_STATUS
831 EFIAPI
832 WinNtGopSimpleTextInExRegisterKeyNotify (
833 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
834 IN EFI_KEY_DATA *KeyData,
835 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
836 OUT VOID **NotifyHandle
837 )
838 /*++
839
840 Routine Description:
841 Register a notification function for a particular keystroke for the input device.
842
843 Arguments:
844 This - Protocol instance pointer.
845 KeyData - A pointer to a buffer that is filled in with the keystroke
846 information data for the key that was pressed.
847 KeyNotificationFunction - Points to the function to be called when the key
848 sequence is typed specified by KeyData.
849 NotifyHandle - Points to the unique handle assigned to the registered notification.
850
851 Returns:
852 EFI_SUCCESS - The notification function was registered successfully.
853 EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.
854 EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL.
855
856 --*/
857 {
858 GOP_PRIVATE_DATA *Private;
859 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify;
860 LIST_ENTRY *Link;
861 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *NewNotify;
862
863 if (KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL) {
864 return EFI_INVALID_PARAMETER;
865 }
866
867 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
868
869 //
870 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
871 //
872 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
873 CurrentNotify = CR (
874 Link,
875 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
876 NotifyEntry,
877 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
878 );
879 if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
880 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
881 *NotifyHandle = CurrentNotify;
882 return EFI_SUCCESS;
883 }
884 }
885 }
886
887 //
888 // Allocate resource to save the notification function
889 //
890 NewNotify = (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) AllocateZeroPool (sizeof (WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY));
891 if (NewNotify == NULL) {
892 return EFI_OUT_OF_RESOURCES;
893 }
894
895 NewNotify->Signature = WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE;
896 NewNotify->KeyNotificationFn = KeyNotificationFunction;
897 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
898 InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);
899
900 *NotifyHandle = NewNotify;
901
902 return EFI_SUCCESS;
903
904 }
905
906 EFI_STATUS
907 EFIAPI
908 WinNtGopSimpleTextInExUnregisterKeyNotify (
909 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
910 IN VOID *NotificationHandle
911 )
912 /*++
913
914 Routine Description:
915 Remove a registered notification function from a particular keystroke.
916
917 Arguments:
918 This - Protocol instance pointer.
919 NotificationHandle - The handle of the notification function being unregistered.
920
921 Returns:
922 EFI_SUCCESS - The notification function was unregistered successfully.
923 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
924
925 --*/
926 {
927 GOP_PRIVATE_DATA *Private;
928 LIST_ENTRY *Link;
929 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify;
930
931 if (NotificationHandle == NULL) {
932 return EFI_INVALID_PARAMETER;
933 }
934
935 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
936
937 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
938 CurrentNotify = CR (
939 Link,
940 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
941 NotifyEntry,
942 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
943 );
944 if (CurrentNotify == NotificationHandle) {
945 //
946 // Remove the notification function from NotifyList and free resources
947 //
948 RemoveEntryList (&CurrentNotify->NotifyEntry);
949
950 gBS->FreePool (CurrentNotify);
951 return EFI_SUCCESS;
952 }
953 }
954
955 //
956 // Can not find the specified Notification Handle
957 //
958 return EFI_INVALID_PARAMETER;
959 }
960
961
962 /**
963 TODO: Add function description
964
965 @param Private TODO: add argument description
966
967 @return TODO: add return values
968
969 **/
970 EFI_STATUS
971 WinNtGopInitializeSimpleTextInForWindow (
972 IN GOP_PRIVATE_DATA *Private
973 )
974 {
975 EFI_STATUS Status;
976
977 GopPrivateCreateQ (Private, &Private->QueueForRead);
978 GopPrivateCreateQ (Private, &Private->QueueForNotify);
979
980 //
981 // Initialize Simple Text In protoocol
982 //
983 Private->SimpleTextIn.Reset = WinNtGopSimpleTextInReset;
984 Private->SimpleTextIn.ReadKeyStroke = WinNtGopSimpleTextInReadKeyStroke;
985
986 Status = gBS->CreateEvent (
987 EVT_NOTIFY_WAIT,
988 TPL_NOTIFY,
989 WinNtGopSimpleTextInWaitForKey,
990 Private,
991 &Private->SimpleTextIn.WaitForKey
992 );
993
994
995 Private->SimpleTextInEx.Reset = WinNtGopSimpleTextInExResetEx;
996 Private->SimpleTextInEx.ReadKeyStrokeEx = WinNtGopSimpleTextInExReadKeyStrokeEx;
997 Private->SimpleTextInEx.SetState = WinNtGopSimpleTextInExSetState;
998 Private->SimpleTextInEx.RegisterKeyNotify = WinNtGopSimpleTextInExRegisterKeyNotify;
999 Private->SimpleTextInEx.UnregisterKeyNotify = WinNtGopSimpleTextInExUnregisterKeyNotify;
1000
1001 Private->SimpleTextInEx.Reset (&Private->SimpleTextInEx, FALSE);
1002
1003 InitializeListHead (&Private->NotifyList);
1004
1005 Status = gBS->CreateEvent (
1006 EVT_NOTIFY_WAIT,
1007 TPL_NOTIFY,
1008 WinNtGopSimpleTextInWaitForKey,
1009 Private,
1010 &Private->SimpleTextInEx.WaitForKeyEx
1011 );
1012 ASSERT_EFI_ERROR (Status);
1013
1014 //
1015 // Create the Timer to trigger hot key notifications
1016 //
1017 Status = gBS->CreateEvent (
1018 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1019 TPL_NOTIFY,
1020 WinNtGopSimpleTextInTimerHandler,
1021 Private,
1022 &Private->TimerEvent
1023 );
1024 ASSERT_EFI_ERROR (Status);
1025
1026 Status = gBS->SetTimer (
1027 Private->TimerEvent,
1028 TimerPeriodic,
1029 KEYBOARD_TIMER_INTERVAL
1030 );
1031 ASSERT_EFI_ERROR (Status);
1032
1033 return Status;
1034 }
1035
1036
1037
1038 /**
1039 TODO: Add function description
1040
1041 @param Private TODO: add argument description
1042
1043 @retval EFI_SUCCESS TODO: Add description for return value
1044
1045 **/
1046 EFI_STATUS
1047 WinNtGopDestroySimpleTextInForWindow (
1048 IN GOP_PRIVATE_DATA *Private
1049 )
1050 {
1051 gBS->CloseEvent (Private->TimerEvent);
1052
1053 GopPrivateDestroyQ (Private, &Private->QueueForRead);
1054 GopPrivateDestroyQ (Private, &Private->QueueForNotify);
1055
1056 return EFI_SUCCESS;
1057 }