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