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