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