1 /** @file
2   PS/2 Mouse driver. Routines that interacts with callers,
3   conforming to EFI driver model.
4 
5 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "Ps2Mouse.h"
17 #include "CommPs2.h"
18 
19 ///
20 /// DriverBinding Protocol Instance
21 ///
22 EFI_DRIVER_BINDING_PROTOCOL gPS2MouseDriver = {
23   PS2MouseDriverSupported,
24   PS2MouseDriverStart,
25   PS2MouseDriverStop,
26   0xa,
27   NULL,
28   NULL
29 };
30 
31 /**
32   Test to see if this driver supports ControllerHandle. Any ControllerHandle
33   than contains a IsaIo protocol can be supported.
34 
35   @param  This                Protocol instance pointer.
36   @param  ControllerHandle    Handle of device to test
37   @param  RemainingDevicePath Optional parameter use to pick a specific child
38                               device to start.
39 
40   @retval EFI_SUCCESS         This driver supports this device
41   @retval EFI_ALREADY_STARTED This driver is already running on this device
42   @retval other               This driver does not support this device
43 
44 **/
45 EFI_STATUS
46 EFIAPI
PS2MouseDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)47 PS2MouseDriverSupported (
48   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
49   IN EFI_HANDLE                     Controller,
50   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
51   )
52 {
53   EFI_STATUS                          Status;
54   EFI_ISA_IO_PROTOCOL                 *IsaIo;
55 
56   Status = EFI_SUCCESS;
57 
58   //
59   // Open the IO Abstraction(s) needed to perform the supported test
60   //
61   Status = gBS->OpenProtocol (
62                   Controller,
63                   &gEfiIsaIoProtocolGuid,
64                   (VOID **) &IsaIo,
65                   This->DriverBindingHandle,
66                   Controller,
67                   EFI_OPEN_PROTOCOL_BY_DRIVER
68                   );
69   if (EFI_ERROR (Status)) {
70     return Status;
71   }
72   //
73   // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
74   //
75   switch (IsaIo->ResourceList->Device.HID) {
76   case EISA_PNP_ID (0xF03):
77   //
78   // Microsoft PS/2 style mouse
79   //
80   case EISA_PNP_ID (0xF13):
81     //
82     // PS/2 Port for PS/2-style Mice
83     //
84     break;
85 
86   case EISA_PNP_ID (0x303):
87     //
88     // IBM Enhanced (101/102-key, PS/2 mouse support)
89     //
90     if (IsaIo->ResourceList->Device.UID == 1) {
91       break;
92     }
93 
94   default:
95     Status = EFI_UNSUPPORTED;
96     break;
97   }
98   //
99   // Close the I/O Abstraction(s) used to perform the supported test
100   //
101   gBS->CloseProtocol (
102          Controller,
103          &gEfiIsaIoProtocolGuid,
104          This->DriverBindingHandle,
105          Controller
106          );
107 
108   return Status;
109 }
110 
111 /**
112   Start this driver on ControllerHandle by opening a IsaIo protocol, creating
113   PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid
114   finally.
115 
116   @param  This                 Protocol instance pointer.
117   @param  ControllerHandle     Handle of device to bind driver to
118   @param  RemainingDevicePath  Optional parameter use to pick a specific child
119                                device to start.
120 
121   @retval EFI_SUCCESS          This driver is added to ControllerHandle
122   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
123   @retval other                This driver does not support this device
124 
125 **/
126 EFI_STATUS
127 EFIAPI
PS2MouseDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)128 PS2MouseDriverStart (
129   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
130   IN EFI_HANDLE                     Controller,
131   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
132   )
133 {
134   EFI_STATUS                          Status;
135   EFI_STATUS                          EmptyStatus;
136   EFI_ISA_IO_PROTOCOL                 *IsaIo;
137   PS2_MOUSE_DEV                       *MouseDev;
138   UINT8                               Data;
139   EFI_TPL                             OldTpl;
140   EFI_STATUS_CODE_VALUE               StatusCode;
141   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
142 
143   StatusCode  = 0;
144   MouseDev    = NULL;
145   IsaIo       = NULL;
146 
147   //
148   // Open the device path protocol
149   //
150   Status = gBS->OpenProtocol (
151                   Controller,
152                   &gEfiDevicePathProtocolGuid,
153                   (VOID **) &ParentDevicePath,
154                   This->DriverBindingHandle,
155                   Controller,
156                   EFI_OPEN_PROTOCOL_BY_DRIVER
157                   );
158   if (EFI_ERROR (Status)) {
159     return Status;
160   }
161   //
162   // Report that the keyboard is being enabled
163   //
164   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
165     EFI_PROGRESS_CODE,
166     EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE,
167     ParentDevicePath
168     );
169 
170   //
171   // Get the ISA I/O Protocol on Controller's handle
172   //
173   Status = gBS->OpenProtocol (
174                   Controller,
175                   &gEfiIsaIoProtocolGuid,
176                   (VOID **) &IsaIo,
177                   This->DriverBindingHandle,
178                   Controller,
179                   EFI_OPEN_PROTOCOL_BY_DRIVER
180                   );
181   if (EFI_ERROR (Status)) {
182     gBS->CloseProtocol (
183            Controller,
184            &gEfiDevicePathProtocolGuid,
185            This->DriverBindingHandle,
186            Controller
187            );
188     return EFI_INVALID_PARAMETER;
189   }
190   //
191   // Raise TPL to avoid keyboard operation impact
192   //
193   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
194 
195   //
196   // Allocate private data
197   //
198   MouseDev = AllocateZeroPool (sizeof (PS2_MOUSE_DEV));
199   if (MouseDev == NULL) {
200     Status = EFI_OUT_OF_RESOURCES;
201     goto ErrorExit;
202   }
203   //
204   // Setup the device instance
205   //
206   MouseDev->Signature       = PS2_MOUSE_DEV_SIGNATURE;
207   MouseDev->Handle          = Controller;
208   MouseDev->SampleRate      = SampleRate20;
209   MouseDev->Resolution      = MouseResolution4;
210   MouseDev->Scaling         = Scaling1;
211   MouseDev->DataPackageSize = 3;
212   MouseDev->IsaIo           = IsaIo;
213   MouseDev->DevicePath      = ParentDevicePath;
214 
215   //
216   // Resolution = 4 counts/mm
217   //
218   MouseDev->Mode.ResolutionX                = 4;
219   MouseDev->Mode.ResolutionY                = 4;
220   MouseDev->Mode.LeftButton                 = TRUE;
221   MouseDev->Mode.RightButton                = TRUE;
222 
223   MouseDev->SimplePointerProtocol.Reset     = MouseReset;
224   MouseDev->SimplePointerProtocol.GetState  = MouseGetState;
225   MouseDev->SimplePointerProtocol.Mode      = &(MouseDev->Mode);
226 
227   //
228   // Initialize keyboard controller if necessary
229   //
230   IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
231   //
232   // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.
233   //
234   if ((Data & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {
235     //
236     // If nobody decodes KBC I/O port, it will read back as 0xFF.
237     // Check the Time-Out and Parity bit to see if it has an active KBC in system
238     //
239     Status     = EFI_DEVICE_ERROR;
240     StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED;
241     goto ErrorExit;
242   }
243 
244   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
245     EFI_PROGRESS_CODE,
246     EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST,
247     ParentDevicePath
248     );
249 
250   if ((Data & KBC_SYSF) != KBC_SYSF) {
251     Status = KbcSelfTest (IsaIo);
252     if (EFI_ERROR (Status)) {
253       StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR;
254       goto ErrorExit;
255     }
256   }
257 
258   KbcEnableAux (IsaIo);
259 
260   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
261     EFI_PROGRESS_CODE,
262     EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT,
263     ParentDevicePath
264     );
265 
266   //
267   // Reset the mouse
268   //
269   Status = MouseDev->SimplePointerProtocol.Reset (
270                      &MouseDev->SimplePointerProtocol,
271                      FeaturePcdGet (PcdPs2MouseExtendedVerification)
272                      );
273   if (EFI_ERROR (Status)) {
274     //
275     // mouse not connected
276     //
277     Status      = EFI_SUCCESS;
278     StatusCode  = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED;
279     goto ErrorExit;
280   }
281 
282   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
283     EFI_PROGRESS_CODE,
284     EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED,
285     ParentDevicePath
286     );
287 
288   //
289   // Setup the WaitForKey event
290   //
291   Status = gBS->CreateEvent (
292                   EVT_NOTIFY_WAIT,
293                   TPL_NOTIFY,
294                   MouseWaitForInput,
295                   MouseDev,
296                   &((MouseDev->SimplePointerProtocol).WaitForInput)
297                   );
298   if (EFI_ERROR (Status)) {
299     Status = EFI_OUT_OF_RESOURCES;
300     goto ErrorExit;
301   }
302   //
303   // Setup a periodic timer, used to poll mouse state
304   //
305   Status = gBS->CreateEvent (
306                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
307                   TPL_NOTIFY,
308                   PollMouse,
309                   MouseDev,
310                   &MouseDev->TimerEvent
311                   );
312   if (EFI_ERROR (Status)) {
313     Status = EFI_OUT_OF_RESOURCES;
314     goto ErrorExit;
315   }
316   //
317   // Start timer to poll mouse (100 samples per second)
318   //
319   Status = gBS->SetTimer (MouseDev->TimerEvent, TimerPeriodic, 100000);
320   if (EFI_ERROR (Status)) {
321     Status = EFI_OUT_OF_RESOURCES;
322     goto ErrorExit;
323   }
324 
325   MouseDev->ControllerNameTable = NULL;
326   AddUnicodeString2 (
327     "eng",
328     gPs2MouseComponentName.SupportedLanguages,
329     &MouseDev->ControllerNameTable,
330     L"PS/2 Mouse Device",
331     TRUE
332     );
333   AddUnicodeString2 (
334     "en",
335     gPs2MouseComponentName2.SupportedLanguages,
336     &MouseDev->ControllerNameTable,
337     L"PS/2 Mouse Device",
338     FALSE
339     );
340 
341 
342   //
343   // Install protocol interfaces for the mouse device.
344   //
345   Status = gBS->InstallMultipleProtocolInterfaces (
346                   &Controller,
347                   &gEfiSimplePointerProtocolGuid,
348                   &MouseDev->SimplePointerProtocol,
349                   NULL
350                   );
351   if (EFI_ERROR (Status)) {
352     goto ErrorExit;
353   }
354 
355   gBS->RestoreTPL (OldTpl);
356 
357   return Status;
358 
359 ErrorExit:
360 
361   if (Status != EFI_DEVICE_ERROR) {
362     KbcDisableAux (IsaIo);
363   }
364 
365   if (StatusCode != 0) {
366     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
367       EFI_ERROR_CODE | EFI_ERROR_MINOR,
368       StatusCode,
369       ParentDevicePath
370       );
371   }
372 
373   if ((MouseDev != NULL) && (MouseDev->SimplePointerProtocol.WaitForInput != NULL)) {
374     gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput);
375   }
376 
377   if ((MouseDev != NULL) && (MouseDev->TimerEvent != NULL)) {
378     gBS->CloseEvent (MouseDev->TimerEvent);
379   }
380 
381   if ((MouseDev != NULL) && (MouseDev->ControllerNameTable != NULL)) {
382     FreeUnicodeStringTable (MouseDev->ControllerNameTable);
383   }
384 
385   if (Status != EFI_DEVICE_ERROR) {
386     //
387     // Since there will be no timer handler for mouse input any more,
388     // exhaust input data just in case there is still mouse data left
389     //
390     EmptyStatus = EFI_SUCCESS;
391     while (!EFI_ERROR (EmptyStatus)) {
392       EmptyStatus = In8042Data (IsaIo, &Data);
393     }
394   }
395 
396   if (MouseDev != NULL) {
397     FreePool (MouseDev);
398   }
399 
400   gBS->CloseProtocol (
401          Controller,
402          &gEfiDevicePathProtocolGuid,
403          This->DriverBindingHandle,
404          Controller
405          );
406 
407   gBS->CloseProtocol (
408          Controller,
409          &gEfiIsaIoProtocolGuid,
410          This->DriverBindingHandle,
411          Controller
412          );
413 
414   gBS->RestoreTPL (OldTpl);
415 
416   return Status;
417 }
418 
419 /**
420   Stop this driver on ControllerHandle. Support stoping any child handles
421   created by this driver.
422 
423   @param  This              Protocol instance pointer.
424   @param  ControllerHandle  Handle of device to stop driver on
425   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
426                             children is zero stop the entire bus driver.
427   @param  ChildHandleBuffer List of Child Handles to Stop.
428 
429   @retval EFI_SUCCESS       This driver is removed ControllerHandle
430   @retval other             This driver was not removed from this device
431 
432 **/
433 EFI_STATUS
434 EFIAPI
PS2MouseDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)435 PS2MouseDriverStop (
436   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
437   IN EFI_HANDLE                     Controller,
438   IN UINTN                          NumberOfChildren,
439   IN EFI_HANDLE                     *ChildHandleBuffer
440   )
441 {
442   EFI_STATUS                  Status;
443   EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;
444   PS2_MOUSE_DEV               *MouseDev;
445   UINT8                       Data;
446 
447   Status = gBS->OpenProtocol (
448                   Controller,
449                   &gEfiSimplePointerProtocolGuid,
450                   (VOID **) &SimplePointerProtocol,
451                   This->DriverBindingHandle,
452                   Controller,
453                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
454                   );
455   if (EFI_ERROR (Status)) {
456     return EFI_SUCCESS;
457   }
458 
459   MouseDev = PS2_MOUSE_DEV_FROM_THIS (SimplePointerProtocol);
460 
461   //
462   // Report that the keyboard is being disabled
463   //
464   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
465     EFI_PROGRESS_CODE,
466     EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE,
467     MouseDev->DevicePath
468     );
469 
470   Status = gBS->UninstallProtocolInterface (
471                   Controller,
472                   &gEfiSimplePointerProtocolGuid,
473                   &MouseDev->SimplePointerProtocol
474                   );
475   if (EFI_ERROR (Status)) {
476     return Status;
477   }
478 
479   //
480   // Cancel mouse data polling timer, close timer event
481   //
482   gBS->SetTimer (MouseDev->TimerEvent, TimerCancel, 0);
483   gBS->CloseEvent (MouseDev->TimerEvent);
484 
485   //
486   // Since there will be no timer handler for mouse input any more,
487   // exhaust input data just in case there is still mouse data left
488   //
489   Status = EFI_SUCCESS;
490   while (!EFI_ERROR (Status)) {
491     Status = In8042Data (MouseDev->IsaIo, &Data);
492   }
493 
494   gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput);
495   FreeUnicodeStringTable (MouseDev->ControllerNameTable);
496   FreePool (MouseDev);
497 
498   gBS->CloseProtocol (
499          Controller,
500          &gEfiDevicePathProtocolGuid,
501          This->DriverBindingHandle,
502          Controller
503          );
504 
505   gBS->CloseProtocol (
506          Controller,
507          &gEfiIsaIoProtocolGuid,
508          This->DriverBindingHandle,
509          Controller
510          );
511 
512   return EFI_SUCCESS;
513 }
514 
515 /**
516   Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system
517 
518   @param This                 - Pointer of simple pointer Protocol.
519   @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip.
520 
521 
522   @retval EFI_SUCCESS         - The command byte is written successfully.
523   @retval EFI_DEVICE_ERROR    - Errors occurred during reseting keyboard.
524 
525 **/
526 EFI_STATUS
527 EFIAPI
MouseReset(IN EFI_SIMPLE_POINTER_PROTOCOL * This,IN BOOLEAN ExtendedVerification)528 MouseReset (
529   IN EFI_SIMPLE_POINTER_PROTOCOL    *This,
530   IN BOOLEAN                        ExtendedVerification
531   )
532 {
533   EFI_STATUS    Status;
534   PS2_MOUSE_DEV *MouseDev;
535   EFI_TPL       OldTpl;
536   BOOLEAN       KeyboardEnable;
537   UINT8         Data;
538 
539   MouseDev = PS2_MOUSE_DEV_FROM_THIS (This);
540 
541   //
542   // Report reset progress code
543   //
544   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
545     EFI_PROGRESS_CODE,
546     EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET,
547     MouseDev->DevicePath
548     );
549 
550   KeyboardEnable = FALSE;
551 
552   //
553   // Raise TPL to avoid keyboard operation impact
554   //
555   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
556 
557   ZeroMem (&MouseDev->State, sizeof (EFI_SIMPLE_POINTER_STATE));
558   MouseDev->StateChanged = FALSE;
559 
560   //
561   // Exhaust input data
562   //
563   Status = EFI_SUCCESS;
564   while (!EFI_ERROR (Status)) {
565     Status = In8042Data (MouseDev->IsaIo, &Data);
566   }
567 
568   CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable);
569 
570   KbcDisableKb (MouseDev->IsaIo);
571 
572   MouseDev->IsaIo->Io.Read (MouseDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
573 
574   //
575   // if there's data block on KBC data port, read it out
576   //
577   if ((Data & KBC_OUTB) == KBC_OUTB) {
578     MouseDev->IsaIo->Io.Read (MouseDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data);
579   }
580 
581   Status = EFI_SUCCESS;
582   //
583   // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system.
584   // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is
585   // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling
586   //
587   if (ExtendedVerification && CheckMouseConnect (MouseDev)) {
588     //
589     // Send mouse reset command and set mouse default configure
590     //
591     Status = PS2MouseReset (MouseDev->IsaIo);
592     if (EFI_ERROR (Status)) {
593       Status = EFI_DEVICE_ERROR;
594       goto Exit;
595     }
596 
597     Status = PS2MouseSetSampleRate (MouseDev->IsaIo, MouseDev->SampleRate);
598     if (EFI_ERROR (Status)) {
599       Status = EFI_DEVICE_ERROR;
600       goto Exit;
601     }
602 
603     Status = PS2MouseSetResolution (MouseDev->IsaIo, MouseDev->Resolution);
604     if (EFI_ERROR (Status)) {
605       Status = EFI_DEVICE_ERROR;
606       goto Exit;
607     }
608 
609     Status = PS2MouseSetScaling (MouseDev->IsaIo, MouseDev->Scaling);
610     if (EFI_ERROR (Status)) {
611       Status = EFI_DEVICE_ERROR;
612       goto Exit;
613     }
614 
615     Status = PS2MouseEnable (MouseDev->IsaIo);
616     if (EFI_ERROR (Status)) {
617       Status = EFI_DEVICE_ERROR;
618       goto Exit;
619     }
620   }
621 Exit:
622   gBS->RestoreTPL (OldTpl);
623 
624   if (KeyboardEnable) {
625     KbcEnableKb (MouseDev->IsaIo);
626   }
627 
628   return Status;
629 }
630 
631 /**
632   Check whether there is Ps/2 mouse device in system
633 
634   @param MouseDev   - Mouse Private Data Structure
635 
636   @retval TRUE      - Keyboard in System.
637   @retval FALSE     - Keyboard not in System.
638 
639 **/
640 BOOLEAN
CheckMouseConnect(IN PS2_MOUSE_DEV * MouseDev)641 CheckMouseConnect (
642   IN  PS2_MOUSE_DEV     *MouseDev
643   )
644 
645 {
646   EFI_STATUS     Status;
647 
648   Status = PS2MouseEnable (MouseDev->IsaIo);
649   if (!EFI_ERROR (Status)) {
650     return TRUE;
651   }
652 
653   return FALSE;
654 }
655 
656 /**
657   Get and Clear mouse status.
658 
659   @param This                 - Pointer of simple pointer Protocol.
660   @param State                - Output buffer holding status.
661 
662   @retval EFI_INVALID_PARAMETER Output buffer is invalid.
663   @retval EFI_NOT_READY         Mouse is not changed status yet.
664   @retval EFI_SUCCESS           Mouse status is changed and get successful.
665 **/
666 EFI_STATUS
667 EFIAPI
MouseGetState(IN EFI_SIMPLE_POINTER_PROTOCOL * This,IN OUT EFI_SIMPLE_POINTER_STATE * State)668 MouseGetState (
669   IN EFI_SIMPLE_POINTER_PROTOCOL    *This,
670   IN OUT EFI_SIMPLE_POINTER_STATE   *State
671   )
672 {
673   PS2_MOUSE_DEV *MouseDev;
674   EFI_TPL       OldTpl;
675 
676   MouseDev = PS2_MOUSE_DEV_FROM_THIS (This);
677 
678   if (State == NULL) {
679     return EFI_INVALID_PARAMETER;
680   }
681 
682   if (!MouseDev->StateChanged) {
683     return EFI_NOT_READY;
684   }
685 
686   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
687   CopyMem (State, &(MouseDev->State), sizeof (EFI_SIMPLE_POINTER_STATE));
688 
689   //
690   // clear mouse state
691   //
692   MouseDev->State.RelativeMovementX = 0;
693   MouseDev->State.RelativeMovementY = 0;
694   MouseDev->State.RelativeMovementZ = 0;
695   MouseDev->StateChanged            = FALSE;
696   gBS->RestoreTPL (OldTpl);
697 
698   return EFI_SUCCESS;
699 }
700 
701 /**
702 
703   Event notification function for SIMPLE_POINTER.WaitForInput event.
704   Signal the event if there is input from mouse.
705 
706   @param Event    event object
707   @param Context  event context
708 
709 **/
710 VOID
711 EFIAPI
MouseWaitForInput(IN EFI_EVENT Event,IN VOID * Context)712 MouseWaitForInput (
713   IN  EFI_EVENT               Event,
714   IN  VOID                    *Context
715   )
716 {
717   PS2_MOUSE_DEV *MouseDev;
718 
719   MouseDev = (PS2_MOUSE_DEV *) Context;
720 
721   //
722   // Someone is waiting on the mouse event, if there's
723   // input from mouse, signal the event
724   //
725   if (MouseDev->StateChanged) {
726     gBS->SignalEvent (Event);
727   }
728 
729 }
730 
731 /**
732   Event notification function for TimerEvent event.
733   If mouse device is connected to system, try to get the mouse packet data.
734 
735   @param Event      -  TimerEvent in PS2_MOUSE_DEV
736   @param Context    -  Pointer to PS2_MOUSE_DEV structure
737 
738 **/
739 VOID
740 EFIAPI
PollMouse(IN EFI_EVENT Event,IN VOID * Context)741 PollMouse (
742   IN EFI_EVENT  Event,
743   IN VOID       *Context
744   )
745 
746 {
747   PS2_MOUSE_DEV *MouseDev;
748 
749   MouseDev = (PS2_MOUSE_DEV *) Context;
750 
751   //
752   // Polling mouse packet data
753   //
754   PS2MouseGetPacket (MouseDev);
755 }
756 
757 /**
758   The user Entry Point for module Ps2Mouse. The user code starts with this function.
759 
760   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
761   @param[in] SystemTable    A pointer to the EFI System Table.
762 
763   @retval EFI_SUCCESS       The entry point is executed successfully.
764   @retval other             Some error occurs when executing this entry point.
765 
766 **/
767 EFI_STATUS
768 EFIAPI
InitializePs2Mouse(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)769 InitializePs2Mouse(
770   IN EFI_HANDLE           ImageHandle,
771   IN EFI_SYSTEM_TABLE     *SystemTable
772   )
773 {
774   EFI_STATUS              Status;
775 
776   //
777   // Install driver model protocol(s).
778   //
779   Status = EfiLibInstallDriverBindingComponentName2 (
780              ImageHandle,
781              SystemTable,
782              &gPS2MouseDriver,
783              ImageHandle,
784              &gPs2MouseComponentName,
785              &gPs2MouseComponentName2
786              );
787   ASSERT_EFI_ERROR (Status);
788 
789 
790   return Status;
791 }
792 
793