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