1/** @file
2  A faked PS/2 Absolute Pointer driver. Routines that interacts with callers,
3  conforming to EFI driver model
4
5Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
6This program and the accompanying materials
7are licensed and made available under the terms and conditions of the BSD License
8which accompanies this distribution.  The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT 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//
22EFI_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**/
45EFI_STATUS
46EFIAPI
47PS2MouseAbsolutePointerDriverSupported (
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**/
126EFI_STATUS
127EFIAPI
128PS2MouseAbsolutePointerDriverStart (
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
349ErrorExit:
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**/
418EFI_STATUS
419EFIAPI
420PS2MouseAbsolutePointerDriverStop (
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**/
511EFI_STATUS
512EFIAPI
513MouseAbsolutePointerReset (
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  }
606Exit:
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**/
625BOOLEAN
626CheckMouseAbsolutePointerConnect (
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**/
651EFI_STATUS
652EFIAPI
653MouseAbsolutePointerGetState (
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**/
696VOID
697EFIAPI
698MouseAbsolutePointerWaitForInput (
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**/
725VOID
726EFIAPI
727PollMouseAbsolutePointer(
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**/
753EFI_STATUS
754EFIAPI
755InitializePs2MouseAbsolutePointer(
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