1 | /** @file
|
---|
2 | VirtualKeyboard driver
|
---|
3 |
|
---|
4 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
---|
5 | Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
|
---|
6 |
|
---|
7 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
8 |
|
---|
9 | **/
|
---|
10 |
|
---|
11 | #include "VirtualKeyboard.h"
|
---|
12 |
|
---|
13 | //
|
---|
14 | // RAM Keyboard Driver Binding Protocol Instance
|
---|
15 | //
|
---|
16 | EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding = {
|
---|
17 | VirtualKeyboardDriverBindingSupported,
|
---|
18 | VirtualKeyboardDriverBindingStart,
|
---|
19 | VirtualKeyboardDriverBindingStop,
|
---|
20 | 0x10,
|
---|
21 | NULL,
|
---|
22 | NULL
|
---|
23 | };
|
---|
24 |
|
---|
25 | //
|
---|
26 | // EFI Driver Binding Protocol Functions
|
---|
27 | //
|
---|
28 |
|
---|
29 | /**
|
---|
30 | Check whether the driver supports this device.
|
---|
31 |
|
---|
32 | @param This The Udriver binding protocol.
|
---|
33 | @param Controller The controller handle to check.
|
---|
34 | @param RemainingDevicePath The remaining device path.
|
---|
35 |
|
---|
36 | @retval EFI_SUCCESS The driver supports this controller.
|
---|
37 | @retval other This device isn't supported.
|
---|
38 |
|
---|
39 | **/
|
---|
40 | EFI_STATUS
|
---|
41 | EFIAPI
|
---|
42 | VirtualKeyboardDriverBindingSupported (
|
---|
43 | IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
---|
44 | IN EFI_HANDLE Controller,
|
---|
45 | IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
---|
46 | )
|
---|
47 | {
|
---|
48 | EFI_STATUS Status;
|
---|
49 | PLATFORM_VIRTUAL_KBD_PROTOCOL *PlatformVirtual;
|
---|
50 |
|
---|
51 | Status = gBS->OpenProtocol (
|
---|
52 | Controller,
|
---|
53 | &gPlatformVirtualKeyboardProtocolGuid,
|
---|
54 | (VOID **) &PlatformVirtual,
|
---|
55 | This->DriverBindingHandle,
|
---|
56 | Controller,
|
---|
57 | EFI_OPEN_PROTOCOL_BY_DRIVER
|
---|
58 | );
|
---|
59 | if (EFI_ERROR (Status)) {
|
---|
60 | return Status;
|
---|
61 | }
|
---|
62 | gBS->CloseProtocol (
|
---|
63 | Controller,
|
---|
64 | &gPlatformVirtualKeyboardProtocolGuid,
|
---|
65 | This->DriverBindingHandle,
|
---|
66 | Controller
|
---|
67 | );
|
---|
68 | return Status;
|
---|
69 | }
|
---|
70 |
|
---|
71 | /**
|
---|
72 | Starts the device with this driver.
|
---|
73 |
|
---|
74 | @param This The driver binding instance.
|
---|
75 | @param Controller Handle of device to bind driver to.
|
---|
76 | @param RemainingDevicePath Optional parameter use to pick a specific child
|
---|
77 | device to start.
|
---|
78 |
|
---|
79 | @retval EFI_SUCCESS The controller is controlled by the driver.
|
---|
80 | @retval Other This controller cannot be started.
|
---|
81 |
|
---|
82 | **/
|
---|
83 | EFI_STATUS
|
---|
84 | EFIAPI
|
---|
85 | VirtualKeyboardDriverBindingStart (
|
---|
86 | IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
---|
87 | IN EFI_HANDLE Controller,
|
---|
88 | IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
---|
89 | )
|
---|
90 | {
|
---|
91 | EFI_STATUS Status;
|
---|
92 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
93 | PLATFORM_VIRTUAL_KBD_PROTOCOL *PlatformVirtual;
|
---|
94 |
|
---|
95 | Status = gBS->OpenProtocol (
|
---|
96 | Controller,
|
---|
97 | &gPlatformVirtualKeyboardProtocolGuid,
|
---|
98 | (VOID **) &PlatformVirtual,
|
---|
99 | This->DriverBindingHandle,
|
---|
100 | Controller,
|
---|
101 | EFI_OPEN_PROTOCOL_BY_DRIVER
|
---|
102 | );
|
---|
103 | if (EFI_ERROR (Status)) {
|
---|
104 | return Status;
|
---|
105 | }
|
---|
106 |
|
---|
107 | //
|
---|
108 | // Allocate the private device structure
|
---|
109 | //
|
---|
110 | VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV));
|
---|
111 | if (VirtualKeyboardPrivate == NULL) {
|
---|
112 | Status = EFI_OUT_OF_RESOURCES;
|
---|
113 | goto Done;
|
---|
114 | }
|
---|
115 |
|
---|
116 | //
|
---|
117 | // Initialize the private device structure
|
---|
118 | //
|
---|
119 | VirtualKeyboardPrivate->Signature = VIRTUAL_KEYBOARD_DEV_SIGNATURE;
|
---|
120 | VirtualKeyboardPrivate->Handle = Controller;
|
---|
121 | VirtualKeyboardPrivate->PlatformVirtual = PlatformVirtual;
|
---|
122 | VirtualKeyboardPrivate->Queue.Front = 0;
|
---|
123 | VirtualKeyboardPrivate->Queue.Rear = 0;
|
---|
124 | VirtualKeyboardPrivate->QueueForNotify.Front = 0;
|
---|
125 | VirtualKeyboardPrivate->QueueForNotify.Rear = 0;
|
---|
126 |
|
---|
127 | VirtualKeyboardPrivate->SimpleTextIn.Reset = VirtualKeyboardReset;
|
---|
128 | VirtualKeyboardPrivate->SimpleTextIn.ReadKeyStroke = VirtualKeyboardReadKeyStroke;
|
---|
129 |
|
---|
130 | VirtualKeyboardPrivate->SimpleTextInputEx.Reset = VirtualKeyboardResetEx;
|
---|
131 | VirtualKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = VirtualKeyboardReadKeyStrokeEx;
|
---|
132 | VirtualKeyboardPrivate->SimpleTextInputEx.SetState = VirtualKeyboardSetState;
|
---|
133 |
|
---|
134 | VirtualKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = VirtualKeyboardRegisterKeyNotify;
|
---|
135 | VirtualKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = VirtualKeyboardUnregisterKeyNotify;
|
---|
136 | InitializeListHead (&VirtualKeyboardPrivate->NotifyList);
|
---|
137 |
|
---|
138 | Status = PlatformVirtual->Register ();
|
---|
139 | if (EFI_ERROR (Status)) {
|
---|
140 | goto Done;
|
---|
141 | }
|
---|
142 |
|
---|
143 | //
|
---|
144 | // Report that the keyboard is being enabled
|
---|
145 | //
|
---|
146 | REPORT_STATUS_CODE (
|
---|
147 | EFI_PROGRESS_CODE,
|
---|
148 | EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE
|
---|
149 | );
|
---|
150 |
|
---|
151 | //
|
---|
152 | // Setup the WaitForKey event
|
---|
153 | //
|
---|
154 | Status = gBS->CreateEvent (
|
---|
155 | EVT_NOTIFY_WAIT,
|
---|
156 | TPL_NOTIFY,
|
---|
157 | VirtualKeyboardWaitForKey,
|
---|
158 | &(VirtualKeyboardPrivate->SimpleTextIn),
|
---|
159 | &((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey)
|
---|
160 | );
|
---|
161 | if (EFI_ERROR (Status)) {
|
---|
162 | (VirtualKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;
|
---|
163 | goto Done;
|
---|
164 | }
|
---|
165 | Status = gBS->CreateEvent (
|
---|
166 | EVT_NOTIFY_WAIT,
|
---|
167 | TPL_NOTIFY,
|
---|
168 | VirtualKeyboardWaitForKeyEx,
|
---|
169 | &(VirtualKeyboardPrivate->SimpleTextInputEx),
|
---|
170 | &(VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)
|
---|
171 | );
|
---|
172 | if (EFI_ERROR (Status)) {
|
---|
173 | VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;
|
---|
174 | goto Done;
|
---|
175 | }
|
---|
176 |
|
---|
177 | //
|
---|
178 | // Setup a periodic timer, used for reading keystrokes at a fixed interval
|
---|
179 | //
|
---|
180 | Status = gBS->CreateEvent (
|
---|
181 | EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
---|
182 | TPL_NOTIFY,
|
---|
183 | VirtualKeyboardTimerHandler,
|
---|
184 | VirtualKeyboardPrivate,
|
---|
185 | &VirtualKeyboardPrivate->TimerEvent
|
---|
186 | );
|
---|
187 | if (EFI_ERROR (Status)) {
|
---|
188 | Status = EFI_OUT_OF_RESOURCES;
|
---|
189 | goto Done;
|
---|
190 | }
|
---|
191 |
|
---|
192 | Status = gBS->SetTimer (
|
---|
193 | VirtualKeyboardPrivate->TimerEvent,
|
---|
194 | TimerPeriodic,
|
---|
195 | KEYBOARD_TIMER_INTERVAL
|
---|
196 | );
|
---|
197 | if (EFI_ERROR (Status)) {
|
---|
198 | Status = EFI_OUT_OF_RESOURCES;
|
---|
199 | goto Done;
|
---|
200 | }
|
---|
201 |
|
---|
202 | Status = gBS->CreateEvent (
|
---|
203 | EVT_NOTIFY_SIGNAL,
|
---|
204 | TPL_CALLBACK,
|
---|
205 | KeyNotifyProcessHandler,
|
---|
206 | VirtualKeyboardPrivate,
|
---|
207 | &VirtualKeyboardPrivate->KeyNotifyProcessEvent
|
---|
208 | );
|
---|
209 | if (EFI_ERROR (Status)) {
|
---|
210 | Status = EFI_OUT_OF_RESOURCES;
|
---|
211 | goto Done;
|
---|
212 | }
|
---|
213 |
|
---|
214 | //
|
---|
215 | // Reset the keyboard device
|
---|
216 | //
|
---|
217 | Status = VirtualKeyboardPrivate->SimpleTextInputEx.Reset (
|
---|
218 | &VirtualKeyboardPrivate->SimpleTextInputEx,
|
---|
219 | FALSE
|
---|
220 | );
|
---|
221 | if (EFI_ERROR (Status)) {
|
---|
222 | DEBUG ((DEBUG_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));
|
---|
223 | goto Done;
|
---|
224 | }
|
---|
225 | //
|
---|
226 | // Install protocol interfaces for the keyboard device.
|
---|
227 | //
|
---|
228 | Status = gBS->InstallMultipleProtocolInterfaces (
|
---|
229 | &Controller,
|
---|
230 | &gEfiSimpleTextInProtocolGuid,
|
---|
231 | &VirtualKeyboardPrivate->SimpleTextIn,
|
---|
232 | &gEfiSimpleTextInputExProtocolGuid,
|
---|
233 | &VirtualKeyboardPrivate->SimpleTextInputEx,
|
---|
234 | NULL
|
---|
235 | );
|
---|
236 |
|
---|
237 | Done:
|
---|
238 | if (EFI_ERROR (Status)) {
|
---|
239 | if (VirtualKeyboardPrivate != NULL) {
|
---|
240 | if ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {
|
---|
241 | gBS->CloseEvent ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey);
|
---|
242 | }
|
---|
243 |
|
---|
244 | if ((VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {
|
---|
245 | gBS->CloseEvent (
|
---|
246 | (VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx
|
---|
247 | );
|
---|
248 | }
|
---|
249 |
|
---|
250 | if (VirtualKeyboardPrivate->KeyNotifyProcessEvent != NULL) {
|
---|
251 | gBS->CloseEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);
|
---|
252 | }
|
---|
253 |
|
---|
254 | VirtualKeyboardFreeNotifyList (&VirtualKeyboardPrivate->NotifyList);
|
---|
255 |
|
---|
256 | if (VirtualKeyboardPrivate->TimerEvent != NULL) {
|
---|
257 | gBS->CloseEvent (VirtualKeyboardPrivate->TimerEvent);
|
---|
258 | }
|
---|
259 | FreePool (VirtualKeyboardPrivate);
|
---|
260 | }
|
---|
261 | }
|
---|
262 |
|
---|
263 | gBS->CloseProtocol (
|
---|
264 | Controller,
|
---|
265 | &gPlatformVirtualKeyboardProtocolGuid,
|
---|
266 | This->DriverBindingHandle,
|
---|
267 | Controller
|
---|
268 | );
|
---|
269 |
|
---|
270 | return Status;
|
---|
271 | }
|
---|
272 |
|
---|
273 | /**
|
---|
274 | Stop the device handled by this driver.
|
---|
275 |
|
---|
276 | @param This The driver binding protocol.
|
---|
277 | @param Controller The controller to release.
|
---|
278 | @param NumberOfChildren The number of handles in ChildHandleBuffer.
|
---|
279 | @param ChildHandleBuffer The array of child handle.
|
---|
280 |
|
---|
281 | @retval EFI_SUCCESS The device was stopped.
|
---|
282 | @retval EFI_DEVICE_ERROR The device could not be stopped due to a
|
---|
283 | device error.
|
---|
284 | @retval Others Fail to uninstall protocols attached on the
|
---|
285 | device.
|
---|
286 |
|
---|
287 | **/
|
---|
288 | EFI_STATUS
|
---|
289 | EFIAPI
|
---|
290 | VirtualKeyboardDriverBindingStop (
|
---|
291 | IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
---|
292 | IN EFI_HANDLE Controller,
|
---|
293 | IN UINTN NumberOfChildren,
|
---|
294 | IN EFI_HANDLE *ChildHandleBuffer
|
---|
295 | )
|
---|
296 | {
|
---|
297 | return EFI_SUCCESS;
|
---|
298 | }
|
---|
299 |
|
---|
300 |
|
---|
301 | /**
|
---|
302 | Enqueue the key.
|
---|
303 |
|
---|
304 | @param Queue The queue to be enqueued.
|
---|
305 | @param KeyData The key data to be enqueued.
|
---|
306 |
|
---|
307 | @retval EFI_NOT_READY The queue is full.
|
---|
308 | @retval EFI_SUCCESS Successfully enqueued the key data.
|
---|
309 |
|
---|
310 | **/
|
---|
311 | EFI_STATUS
|
---|
312 | Enqueue (
|
---|
313 | IN SIMPLE_QUEUE *Queue,
|
---|
314 | IN EFI_KEY_DATA *KeyData
|
---|
315 | )
|
---|
316 | {
|
---|
317 | if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {
|
---|
318 | return EFI_NOT_READY;
|
---|
319 | }
|
---|
320 |
|
---|
321 | CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));
|
---|
322 | Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;
|
---|
323 |
|
---|
324 | return EFI_SUCCESS;
|
---|
325 | }
|
---|
326 |
|
---|
327 | /**
|
---|
328 | Dequeue the key.
|
---|
329 |
|
---|
330 | @param Queue The queue to be dequeued.
|
---|
331 | @param KeyData The key data to be dequeued.
|
---|
332 |
|
---|
333 | @retval EFI_NOT_READY The queue is empty.
|
---|
334 | @retval EFI_SUCCESS Successfully dequeued the key data.
|
---|
335 |
|
---|
336 | **/
|
---|
337 | EFI_STATUS
|
---|
338 | Dequeue (
|
---|
339 | IN SIMPLE_QUEUE *Queue,
|
---|
340 | IN EFI_KEY_DATA *KeyData
|
---|
341 | )
|
---|
342 | {
|
---|
343 | if (Queue->Front == Queue->Rear) {
|
---|
344 | return EFI_NOT_READY;
|
---|
345 | }
|
---|
346 |
|
---|
347 | CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));
|
---|
348 | Queue->Front = (Queue->Front + 1) % QUEUE_MAX_COUNT;
|
---|
349 |
|
---|
350 | return EFI_SUCCESS;
|
---|
351 | }
|
---|
352 |
|
---|
353 | /**
|
---|
354 | Check whether the queue is empty.
|
---|
355 |
|
---|
356 | @param Queue The queue to be checked.
|
---|
357 |
|
---|
358 | @retval EFI_NOT_READY The queue is empty.
|
---|
359 | @retval EFI_SUCCESS The queue is not empty.
|
---|
360 |
|
---|
361 | **/
|
---|
362 | EFI_STATUS
|
---|
363 | CheckQueue (
|
---|
364 | IN SIMPLE_QUEUE *Queue
|
---|
365 | )
|
---|
366 | {
|
---|
367 | if (Queue->Front == Queue->Rear) {
|
---|
368 | return EFI_NOT_READY;
|
---|
369 | }
|
---|
370 |
|
---|
371 | return EFI_SUCCESS;
|
---|
372 | }
|
---|
373 |
|
---|
374 | /**
|
---|
375 | Check key buffer to get the key stroke status.
|
---|
376 |
|
---|
377 | @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
|
---|
378 |
|
---|
379 | @retval EFI_SUCCESS A key is being pressed now.
|
---|
380 | @retval Other No key is now pressed.
|
---|
381 |
|
---|
382 | **/
|
---|
383 | EFI_STATUS
|
---|
384 | EFIAPI
|
---|
385 | VirtualKeyboardCheckForKey (
|
---|
386 | IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
|
---|
387 | )
|
---|
388 | {
|
---|
389 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
390 |
|
---|
391 | VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
|
---|
392 |
|
---|
393 | return CheckQueue (&VirtualKeyboardPrivate->Queue);
|
---|
394 | }
|
---|
395 |
|
---|
396 | /**
|
---|
397 | Free keyboard notify list.
|
---|
398 |
|
---|
399 | @param ListHead The list head
|
---|
400 |
|
---|
401 | @retval EFI_SUCCESS Free the notify list successfully
|
---|
402 | @retval EFI_INVALID_PARAMETER ListHead is invalid.
|
---|
403 |
|
---|
404 | **/
|
---|
405 | EFI_STATUS
|
---|
406 | VirtualKeyboardFreeNotifyList (
|
---|
407 | IN OUT LIST_ENTRY *ListHead
|
---|
408 | )
|
---|
409 | {
|
---|
410 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
|
---|
411 |
|
---|
412 | if (ListHead == NULL) {
|
---|
413 | return EFI_INVALID_PARAMETER;
|
---|
414 | }
|
---|
415 | while (!IsListEmpty (ListHead)) {
|
---|
416 | NotifyNode = CR (
|
---|
417 | ListHead->ForwardLink,
|
---|
418 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
|
---|
419 | NotifyEntry,
|
---|
420 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
|
---|
421 | );
|
---|
422 | RemoveEntryList (ListHead->ForwardLink);
|
---|
423 | gBS->FreePool (NotifyNode);
|
---|
424 | }
|
---|
425 |
|
---|
426 | return EFI_SUCCESS;
|
---|
427 | }
|
---|
428 |
|
---|
429 | /**
|
---|
430 | Judge whether is a registed key
|
---|
431 |
|
---|
432 | @param RegsiteredData A pointer to a buffer that is filled in with
|
---|
433 | the keystroke state data for the key that was
|
---|
434 | registered.
|
---|
435 | @param InputData A pointer to a buffer that is filled in with
|
---|
436 | the keystroke state data for the key that was
|
---|
437 | pressed.
|
---|
438 |
|
---|
439 | @retval TRUE Key be pressed matches a registered key.
|
---|
440 | @retval FALSE Match failed.
|
---|
441 |
|
---|
442 | **/
|
---|
443 | BOOLEAN
|
---|
444 | IsKeyRegistered (
|
---|
445 | IN EFI_KEY_DATA *RegsiteredData,
|
---|
446 | IN EFI_KEY_DATA *InputData
|
---|
447 | )
|
---|
448 |
|
---|
449 | {
|
---|
450 | ASSERT (RegsiteredData != NULL && InputData != NULL);
|
---|
451 |
|
---|
452 | if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
|
---|
453 | (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
|
---|
454 | return FALSE;
|
---|
455 | }
|
---|
456 |
|
---|
457 | //
|
---|
458 | // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means
|
---|
459 | // these state could be ignored.
|
---|
460 | //
|
---|
461 | if ((RegsiteredData->KeyState.KeyShiftState != 0) &&
|
---|
462 | (RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState)) {
|
---|
463 | return FALSE;
|
---|
464 | }
|
---|
465 | if ((RegsiteredData->KeyState.KeyToggleState != 0) &&
|
---|
466 | (RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState)) {
|
---|
467 | return FALSE;
|
---|
468 | }
|
---|
469 |
|
---|
470 | return TRUE;
|
---|
471 |
|
---|
472 | }
|
---|
473 |
|
---|
474 | /**
|
---|
475 | Event notification function for SIMPLE_TEXT_IN.WaitForKey event
|
---|
476 | Signal the event if there is key available
|
---|
477 |
|
---|
478 | @param Event the event object
|
---|
479 | @param Context waiting context
|
---|
480 |
|
---|
481 | **/
|
---|
482 | VOID
|
---|
483 | EFIAPI
|
---|
484 | VirtualKeyboardWaitForKey (
|
---|
485 | IN EFI_EVENT Event,
|
---|
486 | IN VOID *Context
|
---|
487 | )
|
---|
488 | {
|
---|
489 | //
|
---|
490 | // Stall 1ms to give a chance to let other driver interrupt this routine
|
---|
491 | // for their timer event.
|
---|
492 | // e.g. UI setup or Shell, other drivers which are driven by timer event
|
---|
493 | // will have a bad performance during this period,
|
---|
494 | // e.g. usb keyboard driver.
|
---|
495 | // Add a stall period can greatly increate other driver performance during
|
---|
496 | // the WaitForKey is recursivly invoked. 1ms delay will make little impact
|
---|
497 | // to the thunk keyboard driver, and user can not feel the delay at all when
|
---|
498 | // input.
|
---|
499 | //
|
---|
500 | gBS->Stall (1000);
|
---|
501 | //
|
---|
502 | // Use TimerEvent callback function to check whether there's any key pressed
|
---|
503 | //
|
---|
504 | VirtualKeyboardTimerHandler (NULL, VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context));
|
---|
505 |
|
---|
506 | if (!EFI_ERROR (VirtualKeyboardCheckForKey (Context))) {
|
---|
507 | gBS->SignalEvent (Event);
|
---|
508 | }
|
---|
509 | }
|
---|
510 |
|
---|
511 | /**
|
---|
512 | Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
|
---|
513 | event. Signal the event if there is key available
|
---|
514 |
|
---|
515 | @param Event event object
|
---|
516 | @param Context waiting context
|
---|
517 |
|
---|
518 | **/
|
---|
519 | VOID
|
---|
520 | EFIAPI
|
---|
521 | VirtualKeyboardWaitForKeyEx (
|
---|
522 | IN EFI_EVENT Event,
|
---|
523 | IN VOID *Context
|
---|
524 | )
|
---|
525 |
|
---|
526 | {
|
---|
527 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
528 |
|
---|
529 | VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context);
|
---|
530 | VirtualKeyboardWaitForKey (Event, &VirtualKeyboardPrivate->SimpleTextIn);
|
---|
531 |
|
---|
532 | }
|
---|
533 |
|
---|
534 | //
|
---|
535 | // EFI Simple Text In Protocol Functions
|
---|
536 | //
|
---|
537 | /**
|
---|
538 | Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE)
|
---|
539 | then do some extra keyboard validations.
|
---|
540 |
|
---|
541 | @param This Pointer of simple text Protocol.
|
---|
542 | @param ExtendedVerification Whether perform the extra validation of
|
---|
543 | keyboard. True: perform; FALSE: skip.
|
---|
544 |
|
---|
545 | @retval EFI_SUCCESS The command byte is written successfully.
|
---|
546 | @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard.
|
---|
547 |
|
---|
548 | **/
|
---|
549 | EFI_STATUS
|
---|
550 | EFIAPI
|
---|
551 | VirtualKeyboardReset (
|
---|
552 | IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
|
---|
553 | IN BOOLEAN ExtendedVerification
|
---|
554 | )
|
---|
555 | {
|
---|
556 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
557 | EFI_STATUS Status;
|
---|
558 | EFI_TPL OldTpl;
|
---|
559 |
|
---|
560 | VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
|
---|
561 |
|
---|
562 | //
|
---|
563 | // Raise TPL to avoid mouse operation impact
|
---|
564 | //
|
---|
565 | OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
---|
566 |
|
---|
567 | if (VirtualKeyboardPrivate->PlatformVirtual &&
|
---|
568 | VirtualKeyboardPrivate->PlatformVirtual->Reset) {
|
---|
569 | Status = VirtualKeyboardPrivate->PlatformVirtual->Reset ();
|
---|
570 | } else {
|
---|
571 | Status = EFI_INVALID_PARAMETER;
|
---|
572 | }
|
---|
573 |
|
---|
574 | //
|
---|
575 | // resume priority of task level
|
---|
576 | //
|
---|
577 | gBS->RestoreTPL (OldTpl);
|
---|
578 |
|
---|
579 | return Status;
|
---|
580 | }
|
---|
581 |
|
---|
582 | /**
|
---|
583 | Reset the input device and optionally run diagnostics
|
---|
584 |
|
---|
585 | @param This Protocol instance pointer.
|
---|
586 | @param ExtendedVerification Driver may perform diagnostics on reset.
|
---|
587 |
|
---|
588 | @retval EFI_SUCCESS The device was reset.
|
---|
589 | @retval EFI_DEVICE_ERROR The device is not functioning properly and
|
---|
590 | could not be reset.
|
---|
591 |
|
---|
592 | **/
|
---|
593 | EFI_STATUS
|
---|
594 | EFIAPI
|
---|
595 | VirtualKeyboardResetEx (
|
---|
596 | IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
---|
597 | IN BOOLEAN ExtendedVerification
|
---|
598 | )
|
---|
599 | {
|
---|
600 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
601 | EFI_STATUS Status;
|
---|
602 | EFI_TPL OldTpl;
|
---|
603 |
|
---|
604 | VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
|
---|
605 |
|
---|
606 | Status = VirtualKeyboardPrivate->SimpleTextIn.Reset (
|
---|
607 | &VirtualKeyboardPrivate->SimpleTextIn,
|
---|
608 | ExtendedVerification
|
---|
609 | );
|
---|
610 | if (EFI_ERROR (Status)) {
|
---|
611 | return EFI_DEVICE_ERROR;
|
---|
612 | }
|
---|
613 |
|
---|
614 | OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
---|
615 |
|
---|
616 | gBS->RestoreTPL (OldTpl);
|
---|
617 |
|
---|
618 | return EFI_SUCCESS;
|
---|
619 |
|
---|
620 | }
|
---|
621 |
|
---|
622 | /**
|
---|
623 | Reads the next keystroke from the input device. The WaitForKey Event can
|
---|
624 | be used to test for existence of a keystroke via WaitForEvent () call.
|
---|
625 |
|
---|
626 | @param VirtualKeyboardPrivate Virtualkeyboard driver private structure.
|
---|
627 | @param KeyData A pointer to a buffer that is filled in
|
---|
628 | with the keystroke state data for the key
|
---|
629 | that was pressed.
|
---|
630 |
|
---|
631 | @retval EFI_SUCCESS The keystroke information was returned.
|
---|
632 | @retval EFI_NOT_READY There was no keystroke data available.
|
---|
633 | @retval EFI_DEVICE_ERROR The keystroke information was not returned
|
---|
634 | due to hardware errors.
|
---|
635 | @retval EFI_INVALID_PARAMETER KeyData is NULL.
|
---|
636 |
|
---|
637 | **/
|
---|
638 | EFI_STATUS
|
---|
639 | KeyboardReadKeyStrokeWorker (
|
---|
640 | IN VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate,
|
---|
641 | OUT EFI_KEY_DATA *KeyData
|
---|
642 | )
|
---|
643 | {
|
---|
644 | EFI_STATUS Status;
|
---|
645 | EFI_TPL OldTpl;
|
---|
646 | if (KeyData == NULL) {
|
---|
647 | return EFI_INVALID_PARAMETER;
|
---|
648 | }
|
---|
649 |
|
---|
650 | //
|
---|
651 | // Use TimerEvent callback function to check whether there's any key pressed
|
---|
652 | //
|
---|
653 |
|
---|
654 | //
|
---|
655 | // Stall 1ms to give a chance to let other driver interrupt this routine for
|
---|
656 | // their timer event.
|
---|
657 | // e.g. OS loader, other drivers which are driven by timer event will have a
|
---|
658 | // bad performance during this period,
|
---|
659 | // e.g. usb keyboard driver.
|
---|
660 | // Add a stall period can greatly increate other driver performance during
|
---|
661 | // the WaitForKey is recursivly invoked. 1ms delay will make little impact
|
---|
662 | // to the thunk keyboard driver, and user can not feel the delay at all when
|
---|
663 | // input.
|
---|
664 | //
|
---|
665 | gBS->Stall (1000);
|
---|
666 |
|
---|
667 | OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
---|
668 |
|
---|
669 | VirtualKeyboardTimerHandler (NULL, VirtualKeyboardPrivate);
|
---|
670 | //
|
---|
671 | // If there's no key, just return
|
---|
672 | //
|
---|
673 | Status = CheckQueue (&VirtualKeyboardPrivate->Queue);
|
---|
674 | if (EFI_ERROR (Status)) {
|
---|
675 | gBS->RestoreTPL (OldTpl);
|
---|
676 | return EFI_NOT_READY;
|
---|
677 | }
|
---|
678 |
|
---|
679 | Status = Dequeue (&VirtualKeyboardPrivate->Queue, KeyData);
|
---|
680 |
|
---|
681 | gBS->RestoreTPL (OldTpl);
|
---|
682 |
|
---|
683 | return EFI_SUCCESS;
|
---|
684 | }
|
---|
685 |
|
---|
686 | /**
|
---|
687 | Read out the scan code of the key that has just been stroked.
|
---|
688 |
|
---|
689 | @param This Pointer of simple text Protocol.
|
---|
690 | @param Key Pointer for store the key that read out.
|
---|
691 |
|
---|
692 | @retval EFI_SUCCESS The key is read out successfully.
|
---|
693 | @retval other The key reading failed.
|
---|
694 |
|
---|
695 | **/
|
---|
696 | EFI_STATUS
|
---|
697 | EFIAPI
|
---|
698 | VirtualKeyboardReadKeyStroke (
|
---|
699 | IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
|
---|
700 | OUT EFI_INPUT_KEY *Key
|
---|
701 | )
|
---|
702 | {
|
---|
703 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
704 | EFI_STATUS Status;
|
---|
705 | EFI_KEY_DATA KeyData;
|
---|
706 |
|
---|
707 | VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
|
---|
708 |
|
---|
709 | Status = KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, &KeyData);
|
---|
710 | if (EFI_ERROR (Status)) {
|
---|
711 | return Status;
|
---|
712 | }
|
---|
713 |
|
---|
714 | //
|
---|
715 | // Convert the Ctrl+[a-z] to Ctrl+[1-26]
|
---|
716 | //
|
---|
717 | if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
|
---|
718 | if (KeyData.Key.UnicodeChar >= L'a' &&
|
---|
719 | KeyData.Key.UnicodeChar <= L'z') {
|
---|
720 | KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);
|
---|
721 | } else if (KeyData.Key.UnicodeChar >= L'A' &&
|
---|
722 | KeyData.Key.UnicodeChar <= L'Z') {
|
---|
723 | KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);
|
---|
724 | }
|
---|
725 | }
|
---|
726 |
|
---|
727 | CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
|
---|
728 |
|
---|
729 | return EFI_SUCCESS;
|
---|
730 | }
|
---|
731 |
|
---|
732 | /**
|
---|
733 | Reads the next keystroke from the input device. The WaitForKey Event can
|
---|
734 | be used to test for existence of a keystroke via WaitForEvent () call.
|
---|
735 |
|
---|
736 | @param This Protocol instance pointer.
|
---|
737 | @param KeyData A pointer to a buffer that is filled in with the
|
---|
738 | keystroke state data for the key that was pressed.
|
---|
739 |
|
---|
740 | @retval EFI_SUCCESS The keystroke information was returned.
|
---|
741 | @retval EFI_NOT_READY There was no keystroke data available.
|
---|
742 | @retval EFI_DEVICE_ERROR The keystroke information was not returned
|
---|
743 | due to hardware errors.
|
---|
744 | @retval EFI_INVALID_PARAMETER KeyData is NULL.
|
---|
745 |
|
---|
746 | **/
|
---|
747 | EFI_STATUS
|
---|
748 | EFIAPI
|
---|
749 | VirtualKeyboardReadKeyStrokeEx (
|
---|
750 | IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
---|
751 | OUT EFI_KEY_DATA *KeyData
|
---|
752 | )
|
---|
753 | {
|
---|
754 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
755 |
|
---|
756 | if (KeyData == NULL) {
|
---|
757 | return EFI_INVALID_PARAMETER;
|
---|
758 | }
|
---|
759 |
|
---|
760 | VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
|
---|
761 |
|
---|
762 | return KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, KeyData);
|
---|
763 |
|
---|
764 | }
|
---|
765 |
|
---|
766 | /**
|
---|
767 | Set certain state for the input device.
|
---|
768 |
|
---|
769 | @param This Protocol instance pointer.
|
---|
770 | @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
|
---|
771 | state for the input device.
|
---|
772 |
|
---|
773 | @retval EFI_SUCCESS The device state was set successfully.
|
---|
774 | @retval EFI_DEVICE_ERROR The device is not functioning correctly and
|
---|
775 | could not have the setting adjusted.
|
---|
776 | @retval EFI_UNSUPPORTED The device does not have the ability to set
|
---|
777 | its state.
|
---|
778 | @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
|
---|
779 |
|
---|
780 | **/
|
---|
781 | EFI_STATUS
|
---|
782 | EFIAPI
|
---|
783 | VirtualKeyboardSetState (
|
---|
784 | IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
---|
785 | IN EFI_KEY_TOGGLE_STATE *KeyToggleState
|
---|
786 | )
|
---|
787 | {
|
---|
788 | if (KeyToggleState == NULL) {
|
---|
789 | return EFI_INVALID_PARAMETER;
|
---|
790 | }
|
---|
791 |
|
---|
792 | return EFI_SUCCESS;
|
---|
793 | }
|
---|
794 |
|
---|
795 | /**
|
---|
796 | Register a notification function for a particular keystroke for the
|
---|
797 | input device.
|
---|
798 |
|
---|
799 | @param This Protocol instance pointer.
|
---|
800 | @param KeyData A pointer to a buffer that is filled in with
|
---|
801 | the keystroke information data for the key
|
---|
802 | that was pressed.
|
---|
803 | @param KeyNotificationFunction Points to the function to be called when the
|
---|
804 | key sequence is typed specified by KeyData.
|
---|
805 | @param NotifyHandle Points to the unique handle assigned to the
|
---|
806 | registered notification.
|
---|
807 |
|
---|
808 |
|
---|
809 | @retval EFI_SUCCESS The notification function was registered
|
---|
810 | successfully.
|
---|
811 | @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary
|
---|
812 | data structures.
|
---|
813 | @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
|
---|
814 |
|
---|
815 | **/
|
---|
816 | EFI_STATUS
|
---|
817 | EFIAPI
|
---|
818 | VirtualKeyboardRegisterKeyNotify (
|
---|
819 | IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
---|
820 | IN EFI_KEY_DATA *KeyData,
|
---|
821 | IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
|
---|
822 | OUT VOID **NotifyHandle
|
---|
823 | )
|
---|
824 | {
|
---|
825 | EFI_STATUS Status;
|
---|
826 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
827 | EFI_TPL OldTpl;
|
---|
828 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
|
---|
829 | LIST_ENTRY *Link;
|
---|
830 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
|
---|
831 |
|
---|
832 | if (KeyData == NULL ||
|
---|
833 | NotifyHandle == NULL ||
|
---|
834 | KeyNotificationFunction == NULL) {
|
---|
835 | return EFI_INVALID_PARAMETER;
|
---|
836 | }
|
---|
837 |
|
---|
838 | VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
|
---|
839 |
|
---|
840 | //
|
---|
841 | // Enter critical section
|
---|
842 | //
|
---|
843 | OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
---|
844 |
|
---|
845 | //
|
---|
846 | // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already
|
---|
847 | // registered.
|
---|
848 | //
|
---|
849 | for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;
|
---|
850 | Link != &VirtualKeyboardPrivate->NotifyList;
|
---|
851 | Link = Link->ForwardLink) {
|
---|
852 | CurrentNotify = CR (
|
---|
853 | Link,
|
---|
854 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
|
---|
855 | NotifyEntry,
|
---|
856 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
|
---|
857 | );
|
---|
858 | if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
|
---|
859 | if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
|
---|
860 | *NotifyHandle = CurrentNotify;
|
---|
861 | Status = EFI_SUCCESS;
|
---|
862 | goto Exit;
|
---|
863 | }
|
---|
864 | }
|
---|
865 | }
|
---|
866 |
|
---|
867 | //
|
---|
868 | // Allocate resource to save the notification function
|
---|
869 | //
|
---|
870 |
|
---|
871 | NewNotify = (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY));
|
---|
872 | if (NewNotify == NULL) {
|
---|
873 | Status = EFI_OUT_OF_RESOURCES;
|
---|
874 | goto Exit;
|
---|
875 | }
|
---|
876 |
|
---|
877 | NewNotify->Signature = VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
|
---|
878 | NewNotify->KeyNotificationFn = KeyNotificationFunction;
|
---|
879 | CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
|
---|
880 | InsertTailList (&VirtualKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);
|
---|
881 |
|
---|
882 | *NotifyHandle = NewNotify;
|
---|
883 | Status = EFI_SUCCESS;
|
---|
884 |
|
---|
885 | Exit:
|
---|
886 | //
|
---|
887 | // Leave critical section and return
|
---|
888 | //
|
---|
889 | gBS->RestoreTPL (OldTpl);
|
---|
890 | return Status;
|
---|
891 |
|
---|
892 | }
|
---|
893 |
|
---|
894 | /**
|
---|
895 | Remove a registered notification function from a particular keystroke.
|
---|
896 |
|
---|
897 | @param This Protocol instance pointer.
|
---|
898 | @param NotificationHandle The handle of the notification function
|
---|
899 | being unregistered.
|
---|
900 |
|
---|
901 | @retval EFI_SUCCESS The notification function was unregistered
|
---|
902 | successfully.
|
---|
903 | @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
|
---|
904 |
|
---|
905 | **/
|
---|
906 | EFI_STATUS
|
---|
907 | EFIAPI
|
---|
908 | VirtualKeyboardUnregisterKeyNotify (
|
---|
909 | IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
|
---|
910 | IN VOID *NotificationHandle
|
---|
911 | )
|
---|
912 | {
|
---|
913 | EFI_STATUS Status;
|
---|
914 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
915 | EFI_TPL OldTpl;
|
---|
916 | LIST_ENTRY *Link;
|
---|
917 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
|
---|
918 |
|
---|
919 | //
|
---|
920 | // Check incoming notification handle
|
---|
921 | //
|
---|
922 | if (NotificationHandle == NULL) {
|
---|
923 | return EFI_INVALID_PARAMETER;
|
---|
924 | }
|
---|
925 |
|
---|
926 | if (((VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature !=
|
---|
927 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {
|
---|
928 | return EFI_INVALID_PARAMETER;
|
---|
929 | }
|
---|
930 |
|
---|
931 | VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
|
---|
932 |
|
---|
933 | //
|
---|
934 | // Enter critical section
|
---|
935 | //
|
---|
936 | OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
---|
937 |
|
---|
938 | for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;
|
---|
939 | Link != &VirtualKeyboardPrivate->NotifyList;
|
---|
940 | Link = Link->ForwardLink) {
|
---|
941 | CurrentNotify = CR (
|
---|
942 | Link,
|
---|
943 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
|
---|
944 | NotifyEntry,
|
---|
945 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
|
---|
946 | );
|
---|
947 | if (CurrentNotify == NotificationHandle) {
|
---|
948 | //
|
---|
949 | // Remove the notification function from NotifyList and free resources
|
---|
950 | //
|
---|
951 | RemoveEntryList (&CurrentNotify->NotifyEntry);
|
---|
952 |
|
---|
953 | Status = EFI_SUCCESS;
|
---|
954 | goto Exit;
|
---|
955 | }
|
---|
956 | }
|
---|
957 |
|
---|
958 | //
|
---|
959 | // Can not find the specified Notification Handle
|
---|
960 | //
|
---|
961 | Status = EFI_INVALID_PARAMETER;
|
---|
962 |
|
---|
963 | Exit:
|
---|
964 | //
|
---|
965 | // Leave critical section and return
|
---|
966 | //
|
---|
967 | gBS->RestoreTPL (OldTpl);
|
---|
968 | return Status;
|
---|
969 | }
|
---|
970 |
|
---|
971 | /**
|
---|
972 | Timer event handler: read a series of scancodes from 8042
|
---|
973 | and put them into memory scancode buffer.
|
---|
974 | it read as much scancodes to either fill
|
---|
975 | the memory buffer or empty the keyboard buffer.
|
---|
976 | It is registered as running under TPL_NOTIFY
|
---|
977 |
|
---|
978 | @param Event The timer event
|
---|
979 | @param Context A KEYBOARD_CONSOLE_IN_DEV pointer
|
---|
980 |
|
---|
981 | **/
|
---|
982 | VOID
|
---|
983 | EFIAPI
|
---|
984 | VirtualKeyboardTimerHandler (
|
---|
985 | IN EFI_EVENT Event,
|
---|
986 | IN VOID *Context
|
---|
987 | )
|
---|
988 | {
|
---|
989 | EFI_TPL OldTpl;
|
---|
990 | LIST_ENTRY *Link;
|
---|
991 | EFI_KEY_DATA KeyData;
|
---|
992 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
|
---|
993 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
994 | VIRTUAL_KBD_KEY VirtualKey;
|
---|
995 |
|
---|
996 | VirtualKeyboardPrivate = Context;
|
---|
997 |
|
---|
998 | //
|
---|
999 | // Enter critical section
|
---|
1000 | //
|
---|
1001 | OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
---|
1002 |
|
---|
1003 | if (VirtualKeyboardPrivate->PlatformVirtual &&
|
---|
1004 | VirtualKeyboardPrivate->PlatformVirtual->Query) {
|
---|
1005 | if (VirtualKeyboardPrivate->PlatformVirtual->Query (&VirtualKey) ==
|
---|
1006 | FALSE) {
|
---|
1007 | goto Exit;
|
---|
1008 | }
|
---|
1009 | // Found key
|
---|
1010 | KeyData.Key.ScanCode = VirtualKey.Key.ScanCode;
|
---|
1011 | KeyData.Key.UnicodeChar = VirtualKey.Key.UnicodeChar;
|
---|
1012 | KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
|
---|
1013 | KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
|
---|
1014 | if (VirtualKeyboardPrivate->PlatformVirtual->Clear) {
|
---|
1015 | VirtualKeyboardPrivate->PlatformVirtual->Clear (&VirtualKey);
|
---|
1016 | }
|
---|
1017 | } else {
|
---|
1018 | goto Exit;
|
---|
1019 | }
|
---|
1020 |
|
---|
1021 | //
|
---|
1022 | // Signal KeyNotify process event if this key pressed matches any key registered.
|
---|
1023 | //
|
---|
1024 | for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;
|
---|
1025 | Link != &VirtualKeyboardPrivate->NotifyList;
|
---|
1026 | Link = Link->ForwardLink) {
|
---|
1027 | CurrentNotify = CR (
|
---|
1028 | Link,
|
---|
1029 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
|
---|
1030 | NotifyEntry,
|
---|
1031 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
|
---|
1032 | );
|
---|
1033 | if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
|
---|
1034 | //
|
---|
1035 | // The key notification function needs to run at TPL_CALLBACK
|
---|
1036 | // while current TPL is TPL_NOTIFY. It will be invoked in
|
---|
1037 | // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
|
---|
1038 | //
|
---|
1039 | Enqueue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);
|
---|
1040 | gBS->SignalEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);
|
---|
1041 | break;
|
---|
1042 | }
|
---|
1043 | }
|
---|
1044 |
|
---|
1045 | Enqueue (&VirtualKeyboardPrivate->Queue, &KeyData);
|
---|
1046 |
|
---|
1047 | Exit:
|
---|
1048 | //
|
---|
1049 | // Leave critical section and return
|
---|
1050 | //
|
---|
1051 | gBS->RestoreTPL (OldTpl);
|
---|
1052 | }
|
---|
1053 |
|
---|
1054 | /**
|
---|
1055 | Process key notify.
|
---|
1056 |
|
---|
1057 | @param Event Indicates the event that invoke this function.
|
---|
1058 | @param Context Indicates the calling context.
|
---|
1059 | **/
|
---|
1060 | VOID
|
---|
1061 | EFIAPI
|
---|
1062 | KeyNotifyProcessHandler (
|
---|
1063 | IN EFI_EVENT Event,
|
---|
1064 | IN VOID *Context
|
---|
1065 | )
|
---|
1066 | {
|
---|
1067 | EFI_STATUS Status;
|
---|
1068 | VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
|
---|
1069 | EFI_KEY_DATA KeyData;
|
---|
1070 | LIST_ENTRY *Link;
|
---|
1071 | LIST_ENTRY *NotifyList;
|
---|
1072 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
|
---|
1073 | EFI_TPL OldTpl;
|
---|
1074 |
|
---|
1075 | VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) Context;
|
---|
1076 |
|
---|
1077 | //
|
---|
1078 | // Invoke notification functions.
|
---|
1079 | //
|
---|
1080 | NotifyList = &VirtualKeyboardPrivate->NotifyList;
|
---|
1081 | while (TRUE) {
|
---|
1082 | //
|
---|
1083 | // Enter critical section
|
---|
1084 | //
|
---|
1085 | OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
---|
1086 | Status = Dequeue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);
|
---|
1087 | //
|
---|
1088 | // Leave critical section
|
---|
1089 | //
|
---|
1090 | gBS->RestoreTPL (OldTpl);
|
---|
1091 | if (EFI_ERROR (Status)) {
|
---|
1092 | break;
|
---|
1093 | }
|
---|
1094 | for (Link = GetFirstNode (NotifyList);
|
---|
1095 | !IsNull (NotifyList, Link);
|
---|
1096 | Link = GetNextNode (NotifyList, Link)) {
|
---|
1097 | CurrentNotify = CR (Link,
|
---|
1098 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
|
---|
1099 | NotifyEntry,
|
---|
1100 | VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
|
---|
1101 | );
|
---|
1102 | if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
|
---|
1103 | CurrentNotify->KeyNotificationFn (&KeyData);
|
---|
1104 | }
|
---|
1105 | }
|
---|
1106 | }
|
---|
1107 | }
|
---|
1108 |
|
---|
1109 | /**
|
---|
1110 | The user Entry Point for module VirtualKeyboard. The user code starts with
|
---|
1111 | this function.
|
---|
1112 |
|
---|
1113 | @param[in] ImageHandle The firmware allocated handle for the EFI image.
|
---|
1114 | @param[in] SystemTable A pointer to the EFI System Table.
|
---|
1115 |
|
---|
1116 | @retval EFI_SUCCESS The entry point is executed successfully.
|
---|
1117 | @retval other Some error occurs when executing this entry point.
|
---|
1118 |
|
---|
1119 | **/
|
---|
1120 | EFI_STATUS
|
---|
1121 | EFIAPI
|
---|
1122 | InitializeVirtualKeyboard(
|
---|
1123 | IN EFI_HANDLE ImageHandle,
|
---|
1124 | IN EFI_SYSTEM_TABLE *SystemTable
|
---|
1125 | )
|
---|
1126 | {
|
---|
1127 | EFI_STATUS Status;
|
---|
1128 |
|
---|
1129 | //
|
---|
1130 | // Install driver model protocol(s).
|
---|
1131 | //
|
---|
1132 | Status = EfiLibInstallDriverBindingComponentName2 (
|
---|
1133 | ImageHandle,
|
---|
1134 | SystemTable,
|
---|
1135 | &gVirtualKeyboardDriverBinding,
|
---|
1136 | ImageHandle,
|
---|
1137 | &gVirtualKeyboardComponentName,
|
---|
1138 | &gVirtualKeyboardComponentName2
|
---|
1139 | );
|
---|
1140 | ASSERT_EFI_ERROR (Status);
|
---|
1141 |
|
---|
1142 | return Status;
|
---|
1143 | }
|
---|