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