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