⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbmouse.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
  USB_MOUSE_DEV                   *UsbMouseDevice;
  EFI_SIMPLE_POINTER_PROTOCOL     *SimplePointerProtocol;
  EFI_USB_IO_PROTOCOL             *UsbIo;

  //
  // Get our context back.
  //
  Status = gBS->OpenProtocol(
              Controller,
              &gEfiSimplePointerProtocolGuid,
              &SimplePointerProtocol,
              This->DriverBindingHandle,
              Controller,
              EFI_OPEN_PROTOCOL_GET_PROTOCOL
          );

  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  UsbMouseDevice = \
    USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL(SimplePointerProtocol);

  UsbIo = UsbMouseDevice->UsbIo;

  //
  // Delete Mouse Async Interrupt Transfer
  //
  UsbIo->UsbAsyncInterruptTransfer(
            UsbIo,
            UsbMouseDevice->IntEndpointDescriptor->EndpointAddress,
            FALSE,
            UsbMouseDevice->IntEndpointDescriptor->Interval,
            0,
            NULL,
            NULL
          );

  gBS->CloseEvent (UsbMouseDevice->SimplePointerProtocol.WaitForInput);

  Status = gBS->UninstallProtocolInterface(
                  Controller,
                  &gEfiSimplePointerProtocolGuid,
                  &UsbMouseDevice->SimplePointerProtocol
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  gBS->CloseProtocol(
          Controller,
          &gEfiUsbIoProtocolGuid,
          This->DriverBindingHandle,
          Controller
       );

  gBS->FreePool (UsbMouseDevice->InterfaceDescriptor);
  gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor);

  if (UsbMouseDevice->ControllerNameTable) {
    EfiLibFreeUnicodeStringTable (UsbMouseDevice->ControllerNameTable);
  }

  gBS->FreePool (UsbMouseDevice);

  return EFI_SUCCESS;

}

BOOLEAN
IsUsbMouse (
  IN  EFI_USB_IO_PROTOCOL     *UsbIo
  )
/*++

  Routine Description:
    Tell if a Usb Controller is a mouse

  Arguments:
    This              - Protocol instance pointer.

  Returns:
    TRUE              - It is a mouse
    FALSE             - It is not a mouse
--*/
{
  EFI_STATUS                      Status;
  EFI_USB_INTERFACE_DESCRIPTOR    InterfaceDescriptor;

  //
  // Get the Default interface descriptor, now we only
  // suppose it is interface 1
  //
  Status = UsbIo->UsbGetInterfaceDescriptor(
                    UsbIo,
                    &InterfaceDescriptor
                  );

  if(EFI_ERROR(Status)) {
    return FALSE;
  }

  if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&
      (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&
      (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE)
      ) {
    return TRUE;
  }

  return FALSE;
}

static EFI_STATUS
InitializeUsbMouseDevice (
  IN  USB_MOUSE_DEV           *UsbMouseDev
  )
/*++

  Routine Description:
    Initialize the Usb Mouse Device.

  Arguments:
    UsbMouseDev         - Device instance to be initialized

  Returns:
    EFI_SUCCES
    other               - Init error.

--*/
{
  EFI_USB_IO_PROTOCOL         *UsbIo;
  UINT8                       Protocol;
  EFI_STATUS                  Status;
  EFI_USB_HID_DESCRIPTOR      MouseHidDesc;
  UINT8                       *ReportDesc;

  UsbIo = UsbMouseDev->UsbIo;

  //
  // Get HID descriptor
  //
  Status = UsbGetHidDescriptor(
              UsbIo,
              UsbMouseDev->InterfaceDescriptor->InterfaceNumber,
              &MouseHidDesc
           );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  //
  // Get Report descriptor
  //
  if (MouseHidDesc.HidClassDesc[0].DescriptorType != 0x22) {
    return EFI_UNSUPPORTED;
  }

  Status = gBS->AllocatePool(
                  EfiBootServicesData,
                  MouseHidDesc.HidClassDesc[0].DescriptorLength,
                  &ReportDesc
                );
  if (EFI_ERROR(Status)) {
    return EFI_OUT_OF_RESOURCES;
  }
  
  EfiZeroMem(ReportDesc, MouseHidDesc.HidClassDesc[0].DescriptorLength);

  Status = UsbGetReportDescriptor(
              UsbIo,
              UsbMouseDev->InterfaceDescriptor->InterfaceNumber,
              MouseHidDesc.HidClassDesc[0].DescriptorLength,
              ReportDesc
           );

  if(EFI_ERROR(Status)) {
    gBS->FreePool(ReportDesc);
    return Status;
  }

  //
  // Parse report descriptor
  //
  Status = ParseMouseReportDescriptor(
              UsbMouseDev,
              ReportDesc,
              MouseHidDesc.HidClassDesc[0].DescriptorLength
           );

  if(EFI_ERROR(Status)) {
      gBS->FreePool(ReportDesc);
      return Status;
  }

  if(UsbMouseDev->NumberOfButtons >= 1) {
      UsbMouseDev->Mode.LeftButton = TRUE;
  }
  if(UsbMouseDev->NumberOfButtons > 1) {
      UsbMouseDev->Mode.RightButton = TRUE;
  }

//  UsbMouseDev->Mode.ResolutionX = UsbMouseDev->XLogicMax - UsbMouseDev->XLogicMin;
//  UsbMouseDev->Mode.ResolutionY = UsbMouseDev->YLogicMax - UsbMouseDev->YLogicMin;
  UsbMouseDev->Mode.ResolutionX = 8;
  UsbMouseDev->Mode.ResolutionY = 8;
  UsbMouseDev->Mode.ResolutionZ = 0;
  //
  // Here we just assume interface 0 is the mouse interface
  //
  UsbGetProtocolRequest(
    UsbIo,
    0,
    &Protocol
  );

  if (Protocol != BOOT_PROTOCOL) {
    Status = UsbSetProtocolRequest(
               UsbIo,
               0,
               BOOT_PROTOCOL
             );

    if (EFI_ERROR(Status)) {
      gBS->FreePool(ReportDesc);
      return EFI_DEVICE_ERROR;
    }
  }

  //
  // Set indefinite Idle rate for USB Mouse
  //
  UsbSetIdleRequest(
      UsbIo,
      0,
      0,
      0
  );

  gBS->FreePool (ReportDesc);

  return EFI_SUCCESS;
}

/*
static VOID
PrintMouseState(
    IN  EFI_MOUSE_STATE *MouseState
    );
*/

static EFI_STATUS
OnMouseInterruptComplete (
  IN  VOID        *Data,
  IN  UINTN       DataLength,
  IN  VOID        *Context,
  IN  UINT32      Result
  )
/*++

  Routine Description:
    It is called whenever there is data received from async interrupt
    transfer.

  Arguments:
    Data            - Data received.
    DataLength      - Length of Data
    Context         - Passed in context
    Result          - Async Interrupt Transfer result

  Returns:
    EFI_SUCCES
    EFI_DEVICE_ERROR

--*/
{
  USB_MOUSE_DEV               *UsbMouseDev;
  EFI_USB_IO_PROTOCOL         *UsbIo;
  UINT8                       EndpointAddr;
  UINT32                      UsbResult;
  EFI_SIMPLE_POINTER_STATE    TempState;

  UsbMouseDev = (USB_MOUSE_DEV *)Context;
  UsbIo = UsbMouseDev->UsbIo;

  if (Result != EFI_USB_NOERROR) {
    if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
      EndpointAddr = UsbMouseDev->IntEndpointDescriptor->EndpointAddress;

      UsbClearEndpointHalt(
        UsbIo,
        EndpointAddr,
        &UsbResult
      );
    }
    
    UsbIo->UsbAsyncInterruptTransfer(
             UsbIo,
             UsbMouseDev->IntEndpointDescriptor->EndpointAddress,
             FALSE,
             0,
             0,
             NULL,
             NULL
           );
    UsbIo->UsbAsyncInterruptTransfer(
                      UsbIo,
                      UsbMouseDev->IntEndpointDescriptor->EndpointAddress,
                      TRUE,
                      UsbMouseDev->IntEndpointDescriptor->Interval,
                      UsbMouseDev->IntEndpointDescriptor->MaxPacketSize,
                      OnMouseInterruptComplete,
                      UsbMouseDev
                );
    return EFI_DEVICE_ERROR;
  }
  
  if(DataLength == 0 || Data == NULL) {
    return EFI_SUCCESS;
  }

  //
  // Check mouse Data
  //
  TempState.LeftButton = (BOOLEAN)(*(UINT8*)Data & 0x01);
  TempState.RightButton = (BOOLEAN)(*(UINT8*)Data & 0x02);
  TempState.RelativeMovementX = *((INT8*)Data + 1);
  TempState.RelativeMovementY = *((INT8*)Data + 2);
  if(DataLength > 3) {
    TempState.RelativeMovementZ = *((INT8*)Data + 3);
  }
  else {
    TempState.RelativeMovementZ = 0;
  }

  if (TempState.RelativeMovementX != 0 ||
	  TempState.RelativeMovementY != 0 ||
	  TempState.RelativeMovementZ != 0 ||
	  TempState.LeftButton != UsbMouseDev->State.LeftButton ||
	  TempState.RightButton != UsbMouseDev->State.RightButton) {
    UsbMouseDev->State.RelativeMovementX += TempState.RelativeMovementX;
    UsbMouseDev->State.RelativeMovementY += TempState.RelativeMovementY;
    UsbMouseDev->State.RelativeMovementZ += TempState.RelativeMovementZ;
	UsbMouseDev->State.LeftButton = TempState.LeftButton;
	UsbMouseDev->State.RightButton = TempState.RightButton;
    UsbMouseDev->StateChanged = TRUE;
  }

  return EFI_SUCCESS;
}

/*
static VOID
PrintMouseState(
    IN  EFI_MOUSE_STATE *MouseState
    )
{
    Aprint("(%x: %x, %x)\n",
        MouseState->ButtonStates,
        MouseState->dx,
        MouseState->dy
        );
}
*/

static EFI_STATUS
GetMouseState(
  IN   EFI_SIMPLE_POINTER_PROTOCOL  *This,
  OUT  EFI_SIMPLE_POINTER_STATE     *MouseState
)
/*++

  Routine Description:
    Get the mouse state, see SIMPLE POINTER PROTOCOL.
    
  Arguments:
    This              - Protocol instance pointer.
    MouseState        - Current mouse state
    
  Returns:
    EFI_SUCCES
    EFI_INVALID_PARAMETER

--*/
{
  USB_MOUSE_DEV           *MouseDev;

  if (MouseState == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  MouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL(This);

  if (!MouseDev->StateChanged) {
    return EFI_NOT_READY;
  }

  EfiCopyMem(
    MouseState,
    &MouseDev->State,
    sizeof(EFI_SIMPLE_POINTER_STATE)
  );

  //
  // Clear previous move state
  //
  MouseDev->State.RelativeMovementX = 0;
  MouseDev->State.RelativeMovementY = 0;
  MouseDev->State.RelativeMovementZ = 0;
  MouseDev->StateChanged = FALSE;

  return EFI_SUCCESS;
}

static EFI_STATUS
UsbMouseReset(
  IN EFI_SIMPLE_POINTER_PROTOCOL    *This,
  IN BOOLEAN                        ExtendedVerification
  )
/*++

  Routine Description:
    Reset the mouse device, see SIMPLE POINTER PROTOCOL.
    
  Arguments:
    This                  - Protocol instance pointer.
    ExtendedVerification  - Ignored here/
    
  Returns:
    EFI_SUCCES

--*/
{
  USB_MOUSE_DEV     *UsbMouseDev;

  UsbMouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);

  EfiZeroMem (
    &UsbMouseDev->State, 
    sizeof(EFI_SIMPLE_POINTER_STATE)
  );

  return EFI_SUCCESS;
}

static VOID
EFIAPI
UsbMouseWaitForInput (
  IN  EFI_EVENT               Event,
  IN  VOID                    *Context
  )
/*++

Routine Description:

  Event notification function for SIMPLE_POINTER.WaitForInput event
  Signal the event if there is input from mouse

Arguments:

Returns:

--*/
{
  USB_MOUSE_DEV     *UsbMouseDev;

  UsbMouseDev = (USB_MOUSE_DEV*)Context;

  //
  // Someone is waiting on the mouse event, if there's
  // input from mouse, signal the event
  //
  if (UsbMouseDev->StateChanged) {
    gBS->SignalEvent(Event);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -