1 /** @file
2   A faked PS/2 Absolute Pointer 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 "Ps2MouseAbsolutePointer.h"
17 #include "CommPs2.h"
18 
19 //
20 // DriverBinding Protocol Instance
21 //
22 EFI_DRIVER_BINDING_PROTOCOL gPS2MouseAbsolutePointerDriver = {
23   PS2MouseAbsolutePointerDriverSupported,
24   PS2MouseAbsolutePointerDriverStart,
25   PS2MouseAbsolutePointerDriverStop,
26   0x1,
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
PS2MouseAbsolutePointerDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)47 PS2MouseAbsolutePointerDriverSupported (
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 Mouse 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
PS2MouseAbsolutePointerDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)128 PS2MouseAbsolutePointerDriverStart (
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_ABSOLUTE_POINTER_DEV     *MouseAbsolutePointerDev;
138   UINT8                               Data;
139   EFI_TPL                             OldTpl;
140   EFI_STATUS_CODE_VALUE               StatusCode;
141   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
142 
143   StatusCode  = 0;
144   MouseAbsolutePointerDev    = 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   MouseAbsolutePointerDev = AllocateZeroPool (sizeof (PS2_MOUSE_ABSOLUTE_POINTER_DEV));
199   if (MouseAbsolutePointerDev == NULL) {
200     Status = EFI_OUT_OF_RESOURCES;
201     goto ErrorExit;
202   }
203   //
204   // Setup the device instance
205   //
206   MouseAbsolutePointerDev->Signature       = PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE;
207   MouseAbsolutePointerDev->Handle          = Controller;
208   MouseAbsolutePointerDev->SampleRate      = SampleRate20;
209   MouseAbsolutePointerDev->Resolution      = MouseResolution4;
210   MouseAbsolutePointerDev->Scaling         = Scaling1;
211   MouseAbsolutePointerDev->DataPackageSize = 3;
212   MouseAbsolutePointerDev->IsaIo           = IsaIo;
213   MouseAbsolutePointerDev->DevicePath      = ParentDevicePath;
214 
215   //
216   // Resolution = 4 counts/mm
217   //
218   MouseAbsolutePointerDev->Mode.AbsoluteMaxX               = 1024;
219   MouseAbsolutePointerDev->Mode.AbsoluteMinX               = 0;
220   MouseAbsolutePointerDev->Mode.AbsoluteMaxY               = 798;
221   MouseAbsolutePointerDev->Mode.AbsoluteMinY               = 0;
222   MouseAbsolutePointerDev->Mode.AbsoluteMaxZ               = 0;
223   MouseAbsolutePointerDev->Mode.AbsoluteMinZ               = 0;
224   MouseAbsolutePointerDev->Mode.Attributes                 = 0x03;
225 
226   MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset     = MouseAbsolutePointerReset;
227   MouseAbsolutePointerDev->AbsolutePointerProtocol.GetState  = MouseAbsolutePointerGetState;
228   MouseAbsolutePointerDev->AbsolutePointerProtocol.Mode      = &(MouseAbsolutePointerDev->Mode);
229 
230   //
231   // Initialize keyboard controller if necessary
232   //
233   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
234     EFI_PROGRESS_CODE,
235     EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST,
236     ParentDevicePath
237     );
238 
239   IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
240   if ((Data & KBC_SYSF) != KBC_SYSF) {
241     Status = KbcSelfTest (IsaIo);
242     if (EFI_ERROR (Status)) {
243       StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR;
244       goto ErrorExit;
245     }
246   }
247 
248   KbcEnableAux (IsaIo);
249 
250   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
251     EFI_PROGRESS_CODE,
252     EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT,
253     ParentDevicePath
254     );
255 
256   //
257   // Reset the mouse
258   //
259   Status = MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset (
260                      &MouseAbsolutePointerDev->AbsolutePointerProtocol,
261                      FeaturePcdGet (PcdPs2MouseExtendedVerification)
262                      );
263   if (EFI_ERROR (Status)) {
264     //
265     // mouse not connected
266     //
267     Status      = EFI_SUCCESS;
268     StatusCode  = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED;
269     goto ErrorExit;
270   }
271 
272   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
273     EFI_PROGRESS_CODE,
274     EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED,
275     ParentDevicePath
276     );
277 
278   //
279   // Setup the WaitForKey event
280   //
281   Status = gBS->CreateEvent (
282                   EVT_NOTIFY_WAIT,
283                   TPL_NOTIFY,
284                   MouseAbsolutePointerWaitForInput,
285                   MouseAbsolutePointerDev,
286                   &((MouseAbsolutePointerDev->AbsolutePointerProtocol).WaitForInput)
287                   );
288   if (EFI_ERROR (Status)) {
289     Status = EFI_OUT_OF_RESOURCES;
290     goto ErrorExit;
291   }
292   //
293   // Setup a periodic timer, used to poll mouse state
294   //
295   Status = gBS->CreateEvent (
296                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
297                   TPL_NOTIFY,
298                   PollMouseAbsolutePointer,
299                   MouseAbsolutePointerDev,
300                   &MouseAbsolutePointerDev->TimerEvent
301                   );
302   if (EFI_ERROR (Status)) {
303     Status = EFI_OUT_OF_RESOURCES;
304     goto ErrorExit;
305   }
306   //
307   // Start timer to poll mouse (100 samples per second)
308   //
309   Status = gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerPeriodic, 100000);
310   if (EFI_ERROR (Status)) {
311     Status = EFI_OUT_OF_RESOURCES;
312     goto ErrorExit;
313   }
314 
315   MouseAbsolutePointerDev->ControllerNameTable = NULL;
316   AddUnicodeString2 (
317     "eng",
318     gPs2MouseAbsolutePointerComponentName.SupportedLanguages,
319     &MouseAbsolutePointerDev->ControllerNameTable,
320     L"Faked PS/2 Touchpad Device",
321     TRUE
322     );
323   AddUnicodeString2 (
324     "en",
325     gPs2MouseAbsolutePointerComponentName2.SupportedLanguages,
326     &MouseAbsolutePointerDev->ControllerNameTable,
327     L"Faked PS/2 Touchpad Device",
328     FALSE
329     );
330 
331 
332   //
333   // Install protocol interfaces for the mouse device.
334   //
335   Status = gBS->InstallMultipleProtocolInterfaces (
336                   &Controller,
337                   &gEfiAbsolutePointerProtocolGuid,
338                   &MouseAbsolutePointerDev->AbsolutePointerProtocol,
339                   NULL
340                   );
341   if (EFI_ERROR (Status)) {
342     goto ErrorExit;
343   }
344 
345   gBS->RestoreTPL (OldTpl);
346 
347   return Status;
348 
349 ErrorExit:
350 
351   KbcDisableAux (IsaIo);
352 
353   if (StatusCode != 0) {
354     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
355       EFI_ERROR_CODE | EFI_ERROR_MINOR,
356       StatusCode,
357       ParentDevicePath
358       );
359   }
360 
361   if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput != NULL)) {
362     gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput);
363   }
364 
365   if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->TimerEvent != NULL)) {
366     gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent);
367   }
368 
369   if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->ControllerNameTable != NULL)) {
370     FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable);
371   }
372   //
373   // Since there will be no timer handler for mouse input any more,
374   // exhaust input data just in case there is still mouse data left
375   //
376   EmptyStatus = EFI_SUCCESS;
377   while (!EFI_ERROR (EmptyStatus)) {
378     EmptyStatus = In8042Data (IsaIo, &Data);
379   }
380 
381   if (MouseAbsolutePointerDev != NULL) {
382     FreePool (MouseAbsolutePointerDev);
383   }
384 
385   gBS->CloseProtocol (
386          Controller,
387          &gEfiDevicePathProtocolGuid,
388          This->DriverBindingHandle,
389          Controller
390          );
391 
392   gBS->CloseProtocol (
393          Controller,
394          &gEfiIsaIoProtocolGuid,
395          This->DriverBindingHandle,
396          Controller
397          );
398 
399   gBS->RestoreTPL (OldTpl);
400 
401   return Status;
402 }
403 
404 /**
405   Stop this driver on ControllerHandle. Support stoping any child handles
406   created by this driver.
407 
408   @param  This              Protocol instance pointer.
409   @param  ControllerHandle  Handle of device to stop driver on
410   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
411                             children is zero stop the entire bus driver.
412   @param  ChildHandleBuffer List of Child Handles to Stop.
413 
414   @retval EFI_SUCCESS       This driver is removed ControllerHandle
415   @retval other             This driver was not removed from this device
416 
417 **/
418 EFI_STATUS
419 EFIAPI
PS2MouseAbsolutePointerDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)420 PS2MouseAbsolutePointerDriverStop (
421   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
422   IN EFI_HANDLE                     Controller,
423   IN UINTN                          NumberOfChildren,
424   IN EFI_HANDLE                     *ChildHandleBuffer
425   )
426 {
427   EFI_STATUS                            Status;
428   EFI_ABSOLUTE_POINTER_PROTOCOL         *AbsolutePointerProtocol;
429   PS2_MOUSE_ABSOLUTE_POINTER_DEV       *MouseAbsolutePointerDev;
430   UINT8                                 Data;
431 
432   Status = gBS->OpenProtocol (
433                   Controller,
434                   &gEfiAbsolutePointerProtocolGuid,
435                   (VOID **) &AbsolutePointerProtocol,
436                   This->DriverBindingHandle,
437                   Controller,
438                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
439                   );
440   if (EFI_ERROR (Status)) {
441     return EFI_SUCCESS;
442   }
443 
444   MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (AbsolutePointerProtocol);
445 
446   //
447   // Report that the keyboard is being disabled
448   //
449   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
450     EFI_PROGRESS_CODE,
451     EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE,
452     MouseAbsolutePointerDev->DevicePath
453     );
454 
455   Status = gBS->UninstallProtocolInterface (
456                   Controller,
457                   &gEfiAbsolutePointerProtocolGuid,
458                   &MouseAbsolutePointerDev->AbsolutePointerProtocol
459                   );
460   if (EFI_ERROR (Status)) {
461     return Status;
462   }
463 
464   //
465   // Cancel mouse data polling timer, close timer event
466   //
467   gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerCancel, 0);
468   gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent);
469 
470   //
471   // Since there will be no timer handler for mouse input any more,
472   // exhaust input data just in case there is still mouse data left
473   //
474   Status = EFI_SUCCESS;
475   while (!EFI_ERROR (Status)) {
476     Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data);
477   }
478 
479   gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput);
480   FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable);
481   FreePool (MouseAbsolutePointerDev);
482 
483   gBS->CloseProtocol (
484          Controller,
485          &gEfiDevicePathProtocolGuid,
486          This->DriverBindingHandle,
487          Controller
488          );
489 
490   gBS->CloseProtocol (
491          Controller,
492          &gEfiIsaIoProtocolGuid,
493          This->DriverBindingHandle,
494          Controller
495          );
496 
497   return EFI_SUCCESS;
498 }
499 
500 /**
501   Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system.
502 
503   @param This                 - Pointer of simple pointer Protocol.
504   @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip.
505 
506 
507   @retval EFI_SUCCESS         - The command byte is written successfully.
508   @retval EFI_DEVICE_ERROR    - Errors occurred during reseting keyboard.
509 
510 **/
511 EFI_STATUS
512 EFIAPI
MouseAbsolutePointerReset(IN EFI_ABSOLUTE_POINTER_PROTOCOL * This,IN BOOLEAN ExtendedVerification)513 MouseAbsolutePointerReset (
514   IN EFI_ABSOLUTE_POINTER_PROTOCOL    *This,
515   IN BOOLEAN                          ExtendedVerification
516   )
517 {
518   EFI_STATUS                       Status;
519   PS2_MOUSE_ABSOLUTE_POINTER_DEV  *MouseAbsolutePointerDev;
520   EFI_TPL                          OldTpl;
521   BOOLEAN                          KeyboardEnable;
522   UINT8                            Data;
523 
524   MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This);
525 
526   //
527   // Report reset progress code
528   //
529   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
530     EFI_PROGRESS_CODE,
531     EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET,
532     MouseAbsolutePointerDev->DevicePath
533     );
534 
535   KeyboardEnable = FALSE;
536 
537   //
538   // Raise TPL to avoid keyboard operation impact
539   //
540   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
541 
542   ZeroMem (&MouseAbsolutePointerDev->State, sizeof (EFI_ABSOLUTE_POINTER_STATE));
543   MouseAbsolutePointerDev->StateChanged = FALSE;
544 
545   //
546   // Exhaust input data
547   //
548   Status = EFI_SUCCESS;
549   while (!EFI_ERROR (Status)) {
550     Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data);
551   }
552 
553   CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable);
554 
555   KbcDisableKb (MouseAbsolutePointerDev->IsaIo);
556 
557   MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
558 
559   //
560   // if there's data block on KBC data port, read it out
561   //
562   if ((Data & KBC_OUTB) == KBC_OUTB) {
563     MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data);
564   }
565 
566   Status = EFI_SUCCESS;
567   //
568   // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system.
569   // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is
570   // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling
571   //
572   if (ExtendedVerification && CheckMouseAbsolutePointerConnect (MouseAbsolutePointerDev)) {
573     //
574     // Send mouse reset command and set mouse default configure
575     //
576     Status = PS2MouseReset (MouseAbsolutePointerDev->IsaIo);
577     if (EFI_ERROR (Status)) {
578       Status = EFI_DEVICE_ERROR;
579       goto Exit;
580     }
581 
582     Status = PS2MouseSetSampleRate (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->SampleRate);
583     if (EFI_ERROR (Status)) {
584       Status = EFI_DEVICE_ERROR;
585       goto Exit;
586     }
587 
588     Status = PS2MouseSetResolution (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Resolution);
589     if (EFI_ERROR (Status)) {
590       Status = EFI_DEVICE_ERROR;
591       goto Exit;
592     }
593 
594     Status = PS2MouseSetScaling (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Scaling);
595     if (EFI_ERROR (Status)) {
596       Status = EFI_DEVICE_ERROR;
597       goto Exit;
598     }
599 
600     Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo);
601     if (EFI_ERROR (Status)) {
602       Status = EFI_DEVICE_ERROR;
603       goto Exit;
604     }
605   }
606 Exit:
607   gBS->RestoreTPL (OldTpl);
608 
609   if (KeyboardEnable) {
610     KbcEnableKb (MouseAbsolutePointerDev->IsaIo);
611   }
612 
613   return Status;
614 }
615 
616 /**
617   Check whether there is Ps/2 mouse device in system
618 
619   @param MouseAbsolutePointerDev - Absolute Pointer Device Private Data Structure
620 
621   @retval TRUE                - Keyboard in System.
622   @retval FALSE               - Keyboard not in System.
623 
624 **/
625 BOOLEAN
CheckMouseAbsolutePointerConnect(IN PS2_MOUSE_ABSOLUTE_POINTER_DEV * MouseAbsolutePointerDev)626 CheckMouseAbsolutePointerConnect (
627   IN  PS2_MOUSE_ABSOLUTE_POINTER_DEV     *MouseAbsolutePointerDev
628   )
629 
630 {
631   EFI_STATUS     Status;
632 
633   Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo);
634   if (!EFI_ERROR (Status)) {
635     return TRUE;
636   }
637 
638   return FALSE;
639 }
640 
641 /**
642   Get and Clear mouse status.
643 
644   @param This                 - Pointer of simple pointer Protocol.
645   @param State                - Output buffer holding status.
646 
647   @retval EFI_INVALID_PARAMETER Output buffer is invalid.
648   @retval EFI_NOT_READY         Mouse is not changed status yet.
649   @retval EFI_SUCCESS           Mouse status is changed and get successful.
650 **/
651 EFI_STATUS
652 EFIAPI
MouseAbsolutePointerGetState(IN EFI_ABSOLUTE_POINTER_PROTOCOL * This,IN OUT EFI_ABSOLUTE_POINTER_STATE * State)653 MouseAbsolutePointerGetState (
654   IN EFI_ABSOLUTE_POINTER_PROTOCOL     *This,
655   IN OUT EFI_ABSOLUTE_POINTER_STATE    *State
656   )
657 {
658   PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;
659   EFI_TPL       OldTpl;
660 
661   MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This);
662 
663   if (State == NULL) {
664     return EFI_INVALID_PARAMETER;
665   }
666 
667   if (!MouseAbsolutePointerDev->StateChanged) {
668     return EFI_NOT_READY;
669   }
670 
671   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
672   CopyMem (State, &(MouseAbsolutePointerDev->State), sizeof (EFI_ABSOLUTE_POINTER_STATE));
673 
674   //
675   // clear mouse state
676   //
677   MouseAbsolutePointerDev->State.CurrentX = 0;
678   MouseAbsolutePointerDev->State.CurrentY = 0;
679   MouseAbsolutePointerDev->State.CurrentZ = 0;
680   MouseAbsolutePointerDev->State.ActiveButtons = 0x0;
681   MouseAbsolutePointerDev->StateChanged            = FALSE;
682   gBS->RestoreTPL (OldTpl);
683 
684   return EFI_SUCCESS;
685 }
686 
687 /**
688 
689   Event notification function for SIMPLE_POINTER.WaitForInput event.
690   Signal the event if there is input from mouse.
691 
692   @param Event    event object
693   @param Context  event context
694 
695 **/
696 VOID
697 EFIAPI
MouseAbsolutePointerWaitForInput(IN EFI_EVENT Event,IN VOID * Context)698 MouseAbsolutePointerWaitForInput (
699   IN  EFI_EVENT               Event,
700   IN  VOID                    *Context
701   )
702 {
703   PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;
704 
705   MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context;
706 
707   //
708   // Someone is waiting on the mouse event, if there's
709   // input from mouse, signal the event
710   //
711   if (MouseAbsolutePointerDev->StateChanged) {
712     gBS->SignalEvent (Event);
713   }
714 
715 }
716 
717 /**
718   Event notification function for TimerEvent event.
719   If mouse device is connected to system, try to get the mouse packet data.
720 
721   @param Event      -  TimerEvent in PS2_MOUSE_DEV
722   @param Context    -  Pointer to PS2_MOUSE_DEV structure
723 
724 **/
725 VOID
726 EFIAPI
PollMouseAbsolutePointer(IN EFI_EVENT Event,IN VOID * Context)727 PollMouseAbsolutePointer(
728   IN EFI_EVENT  Event,
729   IN VOID       *Context
730   )
731 
732 {
733   PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;
734 
735   MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context;
736 
737   //
738   // Polling mouse packet data
739   //
740   PS2MouseGetPacket (MouseAbsolutePointerDev);
741 }
742 
743 /**
744   The user Entry Point for module Ps2MouseAbsolutePointer. The user code starts with this function.
745 
746   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
747   @param[in] SystemTable    A pointer to the EFI System Table.
748 
749   @retval EFI_SUCCESS       The entry point is executed successfully.
750   @retval other             Some error occurs when executing this entry point.
751 
752 **/
753 EFI_STATUS
754 EFIAPI
InitializePs2MouseAbsolutePointer(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)755 InitializePs2MouseAbsolutePointer(
756   IN EFI_HANDLE           ImageHandle,
757   IN EFI_SYSTEM_TABLE     *SystemTable
758   )
759 {
760   EFI_STATUS              Status;
761 
762   //
763   // Install driver model protocol(s).
764   //
765   Status = EfiLibInstallDriverBindingComponentName2 (
766              ImageHandle,
767              SystemTable,
768              &gPS2MouseAbsolutePointerDriver,
769              ImageHandle,
770              &gPs2MouseAbsolutePointerComponentName,
771              &gPs2MouseAbsolutePointerComponentName2
772              );
773   ASSERT_EFI_ERROR (Status);
774 
775 
776   return Status;
777 }
778 
779