]> git.proxmox.com Git - mirror_edk2.git/blob - Nt32Pkg/WinNtGopDxe/WinNtGopInput.c
1. Add Partial Keystroke Support in Nt32 WinNTGopDxe driver. See the Uefi2.3.1a chapt...
[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 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 **/
160 EFI_STATUS
161 GopPrivateCheckQ (
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
172 BOOLEAN
173 GopPrivateIsKeyRegistered (
174 IN EFI_KEY_DATA *RegsiteredData,
175 IN EFI_KEY_DATA *InputData
176 )
177 /*++
178
179 Routine Description:
180
181 Arguments:
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
188 Returns:
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
218 VOID
219 GopPrivateInvokeRegisteredFunction (
220 IN GOP_PRIVATE_DATA *Private,
221 IN EFI_KEY_DATA *KeyData
222 )
223 /*++
224
225 Routine Description:
226
227 This function updates the status light of NumLock, ScrollLock and CapsLock.
228
229 Arguments:
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
235 Returns:
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
257 VOID
258 WinNtGopSimpleTextInTimerHandler (
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 **/
282 EFI_STATUS
283 GopPrivateAddKey (
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 //
366 // Convert Ctrl+[A-Z] to Ctrl+[1-26]
367 //
368 if (Private->LeftCtrl || Private->RightCtrl) {
369 if ((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) {
370 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'a' + 1);
371 } else if ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) {
372 KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'A' + 1);
373 }
374 }
375 GopPrivateAddQ (Private, &Private->QueueForRead, &KeyData);
376
377 return EFI_SUCCESS;
378 }
379
380 EFI_STATUS
381 GopPrivateUpdateStatusLight (
382 IN GOP_PRIVATE_DATA *Private
383 )
384 /*++
385
386 Routine Description:
387
388 This function updates the status light of NumLock, ScrollLock and CapsLock.
389
390 Arguments:
391
392 Private - The private structure of WinNt console In/Out.
393
394 Returns:
395
396 EFI_SUCCESS - The status light is updated successfully.
397
398 --*/
399 {
400 //
401 // BUGBUG:Only SendInput/keybd_event function can toggle
402 // NumLock, CapsLock and ScrollLock keys.
403 // Neither of these functions is included in EFI_WIN_NT_THUNK_PROTOCOL.
404 // Thus, return immediately without operation.
405 //
406 return EFI_SUCCESS;
407
408 }
409
410
411 EFI_STATUS
412 GopPrivateResetWorker (
413 IN GOP_PRIVATE_DATA *Private
414 )
415 /*++
416
417 Routine Description:
418
419 This function is a worker function for SimpleTextIn/SimpleTextInEx.Reset().
420
421 Arguments:
422
423 Private - WinNT GOP private structure
424
425 Returns:
426
427 EFI_SUCCESS - Reset successfully
428
429 --*/
430 {
431 EFI_KEY_DATA KeyData;
432 EFI_TPL OldTpl;
433
434 //
435 // Enter critical section
436 //
437 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
438
439 //
440 // A reset is draining the Queue
441 //
442 while (GopPrivateDeleteQ (Private, &Private->QueueForRead, &KeyData) == EFI_SUCCESS)
443 ;
444 while (GopPrivateDeleteQ (Private, &Private->QueueForNotify, &KeyData) == EFI_SUCCESS)
445 ;
446
447 Private->LeftShift = FALSE;
448 Private->RightShift = FALSE;
449 Private->LeftAlt = FALSE;
450 Private->RightAlt = FALSE;
451 Private->LeftCtrl = FALSE;
452 Private->RightCtrl = FALSE;
453 Private->LeftLogo = FALSE;
454 Private->RightLogo = FALSE;
455 Private->Menu = FALSE;
456 Private->SysReq = FALSE;
457
458 Private->CapsLock = FALSE;
459 Private->NumLock = FALSE;
460 Private->ScrollLock = FALSE;
461 Private->IsPartialKeySupport = FALSE;
462
463 Private->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
464 Private->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
465
466 //
467 // Leave critical section and return
468 //
469 gBS->RestoreTPL (OldTpl);
470
471 return EFI_SUCCESS;
472 }
473
474 EFI_STATUS
475 GopPrivateReadKeyStrokeWorker (
476 IN GOP_PRIVATE_DATA *Private,
477 OUT EFI_KEY_DATA *KeyData
478 )
479 /*++
480
481 Routine Description:
482 Reads the next keystroke from the input device. The WaitForKey Event can
483 be used to test for existance of a keystroke via WaitForEvent () call.
484
485 Arguments:
486 Private - The private structure of WinNt Gop device.
487 KeyData - A pointer to a buffer that is filled in with the keystroke
488 state data for the key that was pressed.
489
490 Returns:
491 EFI_SUCCESS - The keystroke information was returned.
492 EFI_NOT_READY - There was no keystroke data availiable.
493 EFI_DEVICE_ERROR - The keystroke information was not returned due to
494 hardware errors.
495 EFI_INVALID_PARAMETER - KeyData is NULL.
496
497 --*/
498 {
499 EFI_STATUS Status;
500 EFI_TPL OldTpl;
501
502 if (KeyData == NULL) {
503 return EFI_INVALID_PARAMETER;
504 }
505
506 //
507 // Enter critical section
508 //
509 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
510
511 //
512 // Call hot key callback before telling caller there is a key available
513 //
514 WinNtGopSimpleTextInTimerHandler (NULL, Private);
515
516 Status = GopPrivateCheckQ (&Private->QueueForRead);
517 if (!EFI_ERROR (Status)) {
518 //
519 // If a Key press exists try and read it.
520 //
521 Status = GopPrivateDeleteQ (Private, &Private->QueueForRead, KeyData);
522 if (!EFI_ERROR (Status)) {
523 //
524 // If partial keystroke is not enabled, check whether it is value key. If not return
525 // EFI_NOT_READY.
526 //
527 if (!Private->IsPartialKeySupport) {
528 if (KeyData->Key.ScanCode == SCAN_NULL && KeyData->Key.UnicodeChar == CHAR_NULL) {
529 Status = EFI_NOT_READY;
530 }
531 }
532 }
533 }
534
535 //
536 // Leave critical section and return
537 //
538 gBS->RestoreTPL (OldTpl);
539
540 return Status;
541
542 }
543
544
545 //
546 // Simple Text In implementation.
547 //
548
549
550 /**
551 TODO: Add function description
552
553 @param This TODO: add argument description
554 @param ExtendedVerification TODO: add argument description
555
556 @retval EFI_SUCCESS TODO: Add description for return value
557
558 **/
559 EFI_STATUS
560 EFIAPI
561 WinNtGopSimpleTextInReset (
562 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
563 IN BOOLEAN ExtendedVerification
564 )
565 {
566 GOP_PRIVATE_DATA *Private;
567
568 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This);
569
570 return GopPrivateResetWorker (Private);
571 }
572
573
574 /**
575 TODO: Add function description
576
577 @param This TODO: add argument description
578 @param Key TODO: add argument description
579
580 @return TODO: add return values
581
582 **/
583 EFI_STATUS
584 EFIAPI
585 WinNtGopSimpleTextInReadKeyStroke (
586 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
587 OUT EFI_INPUT_KEY *Key
588 )
589 {
590 GOP_PRIVATE_DATA *Private;
591 EFI_STATUS Status;
592 EFI_KEY_DATA KeyData;
593
594 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This);
595 //
596 // Considering if the partial keystroke is enabled, there maybe a partial
597 // keystroke in the queue, so here skip the partial keystroke and get the
598 // next key from the queue
599 //
600 while (1) {
601 Status = GopPrivateReadKeyStrokeWorker (Private, &KeyData);
602 if (EFI_ERROR (Status)) {
603 return Status;
604 }
605 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
606 continue;
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 **/
623 VOID
624 EFIAPI
625 WinNtGopSimpleTextInWaitForKey (
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
687 EFI_STATUS
688 EFIAPI
689 WinNtGopSimpleTextInExResetEx (
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
714 EFI_STATUS
715 EFIAPI
716 WinNtGopSimpleTextInExReadKeyStrokeEx (
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
752 EFI_STATUS
753 EFIAPI
754 WinNtGopSimpleTextInExSetState (
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
819 EFI_STATUS
820 EFIAPI
821 WinNtGopSimpleTextInExRegisterKeyNotify (
822 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
823 IN EFI_KEY_DATA *KeyData,
824 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
825 OUT EFI_HANDLE *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->NotifyHandle;
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 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;
887 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
888 InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);
889
890 *NotifyHandle = NewNotify->NotifyHandle;
891
892 return EFI_SUCCESS;
893
894 }
895
896 EFI_STATUS
897 EFIAPI
898 WinNtGopSimpleTextInExUnregisterKeyNotify (
899 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
900 IN EFI_HANDLE NotificationHandle
901 )
902 /*++
903
904 Routine Description:
905 Remove a registered notification function from a particular keystroke.
906
907 Arguments:
908 This - Protocol instance pointer.
909 NotificationHandle - The handle of the notification function being unregistered.
910
911 Returns:
912 EFI_SUCCESS - The notification function was unregistered successfully.
913 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
914
915 --*/
916 {
917 GOP_PRIVATE_DATA *Private;
918 LIST_ENTRY *Link;
919 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify;
920
921 if (NotificationHandle == NULL) {
922 return EFI_INVALID_PARAMETER;
923 }
924
925 if (((WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) NotificationHandle)->Signature != WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE) {
926 return EFI_INVALID_PARAMETER;
927 }
928
929 Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
930
931 for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
932 CurrentNotify = CR (
933 Link,
934 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
935 NotifyEntry,
936 WIN_NT_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
937 );
938 if (CurrentNotify->NotifyHandle == NotificationHandle) {
939 //
940 // Remove the notification function from NotifyList and free resources
941 //
942 RemoveEntryList (&CurrentNotify->NotifyEntry);
943
944 gBS->FreePool (CurrentNotify);
945 return EFI_SUCCESS;
946 }
947 }
948
949 //
950 // Can not find the specified Notification Handle
951 //
952 return EFI_INVALID_PARAMETER;
953 }
954
955
956 /**
957 TODO: Add function description
958
959 @param Private TODO: add argument description
960
961 @return TODO: add return values
962
963 **/
964 EFI_STATUS
965 WinNtGopInitializeSimpleTextInForWindow (
966 IN GOP_PRIVATE_DATA *Private
967 )
968 {
969 EFI_STATUS Status;
970
971 GopPrivateCreateQ (Private, &Private->QueueForRead);
972 GopPrivateCreateQ (Private, &Private->QueueForNotify);
973
974 //
975 // Initialize Simple Text In protoocol
976 //
977 Private->SimpleTextIn.Reset = WinNtGopSimpleTextInReset;
978 Private->SimpleTextIn.ReadKeyStroke = WinNtGopSimpleTextInReadKeyStroke;
979
980 Status = gBS->CreateEvent (
981 EVT_NOTIFY_WAIT,
982 TPL_NOTIFY,
983 WinNtGopSimpleTextInWaitForKey,
984 Private,
985 &Private->SimpleTextIn.WaitForKey
986 );
987
988
989 Private->SimpleTextInEx.Reset = WinNtGopSimpleTextInExResetEx;
990 Private->SimpleTextInEx.ReadKeyStrokeEx = WinNtGopSimpleTextInExReadKeyStrokeEx;
991 Private->SimpleTextInEx.SetState = WinNtGopSimpleTextInExSetState;
992 Private->SimpleTextInEx.RegisterKeyNotify = WinNtGopSimpleTextInExRegisterKeyNotify;
993 Private->SimpleTextInEx.UnregisterKeyNotify = WinNtGopSimpleTextInExUnregisterKeyNotify;
994
995 Private->SimpleTextInEx.Reset (&Private->SimpleTextInEx, FALSE);
996
997 InitializeListHead (&Private->NotifyList);
998
999 Status = gBS->CreateEvent (
1000 EVT_NOTIFY_WAIT,
1001 TPL_NOTIFY,
1002 WinNtGopSimpleTextInWaitForKey,
1003 Private,
1004 &Private->SimpleTextInEx.WaitForKeyEx
1005 );
1006 ASSERT_EFI_ERROR (Status);
1007
1008 //
1009 // Create the Timer to trigger hot key notifications
1010 //
1011 Status = gBS->CreateEvent (
1012 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1013 TPL_NOTIFY,
1014 WinNtGopSimpleTextInTimerHandler,
1015 Private,
1016 &Private->TimerEvent
1017 );
1018 ASSERT_EFI_ERROR (Status);
1019
1020 Status = gBS->SetTimer (
1021 Private->TimerEvent,
1022 TimerPeriodic,
1023 KEYBOARD_TIMER_INTERVAL
1024 );
1025 ASSERT_EFI_ERROR (Status);
1026
1027 return Status;
1028 }
1029
1030
1031
1032 /**
1033 TODO: Add function description
1034
1035 @param Private TODO: add argument description
1036
1037 @retval EFI_SUCCESS TODO: Add description for return value
1038
1039 **/
1040 EFI_STATUS
1041 WinNtGopDestroySimpleTextInForWindow (
1042 IN GOP_PRIVATE_DATA *Private
1043 )
1044 {
1045 gBS->CloseEvent (Private->TimerEvent);
1046
1047 GopPrivateDestroyQ (Private, &Private->QueueForRead);
1048 GopPrivateDestroyQ (Private, &Private->QueueForNotify);
1049
1050 return EFI_SUCCESS;
1051 }