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