alder_lake_bios/Insyde/InsydeModulePkg/Bus/Usb/UsbTouchPanelDxe/UsbTouchPanel.c

1504 lines
45 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2012 - 2018, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "UsbTouchPanel.h"
#include <PostCode.h>
//
// Prototypes
// Driver model protocol interface
//
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
EFI_DRIVER_BINDING_PROTOCOL gUsbTouchPanelDriverBinding = {
UsbTouchPanelDriverBindingSupported,
UsbTouchPanelDriverBindingStart,
UsbTouchPanelDriverBindingStop,
0x12,
NULL,
NULL
};
//
// helper functions
//
STATIC
BOOLEAN
IsUsbTouchPanel (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN EFI_USB_CORE_PROTOCOL *UsbCore
);
STATIC
EFI_STATUS
InitializeUsbTouchPanelDevice (
IN USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice
);
STATIC
VOID
EFIAPI
UsbTouchPanelWaitForInput (
IN EFI_EVENT Event,
IN VOID *Context
);
STATIC
VOID
EFIAPI
DisconnectUsbTouchPanel (
IN EFI_EVENT Event,
IN VOID *Context
);
//
// Touch Panel interrupt handler
//
STATIC
EFI_STATUS
EFIAPI
OnTouchPanelInterruptComplete (
IN VOID *Data,
IN UINTN DataLength,
IN VOID *Context,
IN UINT32 Result
);
//
// Touch Panel Protocol
//
STATIC
EFI_STATUS
EFIAPI
GetTouchPanelState (
IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
OUT EFI_ABSOLUTE_POINTER_STATE *TouchPanelState
);
STATIC
EFI_STATUS
EFIAPI
UsbTouchPanelReset (
IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
STATIC
VOID
EFIAPI
UsbTouchPanelRecoveryHandler (
IN UINTN Event,
IN VOID *Context
);
STATIC
VOID
TouchPanelReportStatusCode (
IN USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice,
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value
);
/**
Entry point for EFI drivers.
@param ImageHandle EFI_HANDLE
@param SystemTable EFI_SYSTEM_TABLE
@retval EFI_SUCCESS
@retval others
**/
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Install binding protocols
//
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gUsbTouchPanelDriverBinding,
ImageHandle,
&gUsbTouchPanelComponentName,
&gUsbTouchPanelComponentName2
);
}
/**
Test to see if this driver supports ControllerHandle. Any ControllerHandle
that has UsbHcProtocol installed will be supported.
@param This Protocol instance pointer.
@param Controller Handle of device to test
@param RemainingDevicePath Not used
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_UNSUPPORTED This driver does not support this device.
**/
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS OpenStatus;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_STATUS Status;
EFI_DEV_PATH_PTR Node;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_USB_CORE_PROTOCOL *UsbCore;
//
// Check Device Path
//
if (RemainingDevicePath != NULL) {
Node.DevPath = RemainingDevicePath;
if (Node.DevPath->Type != MESSAGING_DEVICE_PATH ||
Node.DevPath->SubType != MSG_USB_CLASS_DP ||
DevicePathNodeLength(Node.DevPath) != sizeof(USB_CLASS_DEVICE_PATH) ||
Node.UsbClass->DeviceClass != CLASS_HID) {
return EFI_UNSUPPORTED;
}
}
OpenStatus = gBS->OpenProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
return EFI_UNSUPPORTED;
}
if (OpenStatus == EFI_ALREADY_STARTED) {
return EFI_ALREADY_STARTED;
}
//
// Get the device path for CheckIgnoredDevice
//
Status = gBS->HandleProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID **)&DevicePath
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Setup the data for UsbLegacy
//
Status = gBS->LocateProtocol (
&gEfiUsbCoreProtocolGuid,
NULL,
(VOID **)&UsbCore
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
#if (KEEP_USBIO_FOR_IGNORED_DEVICE == 1)
//
// Filter out the USB devices which in the UsbIgnoreDevice list
//
Status = UsbCore->CheckIgnoredDevice(DevicePath, UsbIo);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
#endif
//
// Use the USB I/O protocol interface to see the Controller is
// the Touch Panel controller that can be managed by this driver.
//
Status = EFI_SUCCESS;
if (!IsUsbTouchPanel (UsbIo, UsbCore)) {
Status = EFI_UNSUPPORTED;
}
ErrorExit:
gBS->CloseProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
return Status;
}
/**
Starting the Usb Bus Driver
@param This Protocol instance pointer.
@param Controller Handle of device to test
@param RemainingDevicePath Not used
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_UNSUPPORTED This driver does not support this device.
@retval EFI_DEVICE_ERROR This driver cannot be started due to device error
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources
@retval EFI_ALREADY_STARTED Thios driver has been started
**/
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_CORE_PROTOCOL *UsbCore;
EFI_USB_ENDPOINT_DESCRIPTOR EndpointDesc;
USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice;
UINT8 EndpointNumber;
UINT8 Index;
UINT8 EndpointAddr;
UINT8 PollingInterval;
UINT8 PacketSize;
BOOLEAN EndpointFound;
EFI_EVENT LegacyBootEvent;
EFI_EVENT ExitBootServicesEvent;
POST_CODE (BDS_CONNECT_USB_DEVICE);
UsbTouchPanelDevice = NULL;
UsbCore = NULL;
Status = EFI_SUCCESS;
LegacyBootEvent = NULL;
ExitBootServicesEvent = NULL;
Status = gBS->OpenProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Locate EFI_USB_CORE_PROTOCOL for further use
//
Status = gBS->LocateProtocol (
&gEfiUsbCoreProtocolGuid,
NULL,
(VOID **)&UsbCore
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
Status = UsbCore->AllocateBuffer (
sizeof (USB_TOUCH_PANEL_DEV),
ALIGNMENT_32,
(VOID **)&UsbTouchPanelDevice
);
if (EFI_ERROR(Status)) {
Status = EFI_OUT_OF_RESOURCES;
goto ErrorExit;
}
UsbTouchPanelDevice->UsbIo = UsbIo;
UsbTouchPanelDevice->UsbCore = UsbCore;
UsbTouchPanelDevice->Signature = USB_TOUCH_PANEL_DEV_SIGNATURE;
//
// Get the Device Path Protocol on Controller's handle
//
Status = gBS->OpenProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
(VOID **) &UsbTouchPanelDevice->DevicePath,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Get interface & endpoint descriptor
//
UsbIo->UsbGetInterfaceDescriptor (
UsbIo,
&UsbTouchPanelDevice->InterfaceDescriptor
);
EndpointNumber = UsbTouchPanelDevice->InterfaceDescriptor.NumEndpoints;
for (Index = 0, EndpointFound = FALSE; Index < EndpointNumber; Index++) {
UsbIo->UsbGetEndpointDescriptor (
UsbIo,
Index,
&EndpointDesc
);
if ((EndpointDesc.Attributes & 0x03) == 0x03 && (EndpointDesc.EndpointAddress & 0x80)) {
//
// We only care interrupt endpoint here
//
UsbTouchPanelDevice->IntEndpointDescriptor = EndpointDesc;
EndpointFound = TRUE;
break;
}
}
if (!EndpointFound) {
//
// No interrupt endpoint, then error
//
Status = EFI_UNSUPPORTED;
goto ErrorExit;
}
Status = InitializeUsbTouchPanelDevice (UsbTouchPanelDevice);
if (EFI_ERROR (Status)) {
TouchPanelReportStatusCode (
UsbTouchPanelDevice,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
(EFI_PERIPHERAL_TOUCH_PANEL | EFI_P_EC_INTERFACE_ERROR)
);
goto ErrorExit;
}
UsbTouchPanelDevice->AbsolutePointerProtocol.GetState = GetTouchPanelState;
UsbTouchPanelDevice->AbsolutePointerProtocol.Reset = UsbTouchPanelReset;
UsbTouchPanelDevice->AbsolutePointerProtocol.Mode = &UsbTouchPanelDevice->Mode;
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
UsbTouchPanelWaitForInput,
UsbTouchPanelDevice,
&((UsbTouchPanelDevice->AbsolutePointerProtocol).WaitForInput)
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
Status = gBS->InstallProtocolInterface (
&Controller,
&gEfiAbsolutePointerProtocolGuid,
EFI_NATIVE_INTERFACE,
&UsbTouchPanelDevice->AbsolutePointerProtocol
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto ErrorExit;
}
//
// After Enabling Async Interrupt Transfer on this Touch Panel Device
// we will be able to get key data from it. Thus this is deemed as
// the enable action of the Touch Panel
//
TouchPanelReportStatusCode (
UsbTouchPanelDevice,
EFI_PROGRESS_CODE,
(EFI_PERIPHERAL_TOUCH_PANEL | EFI_P_PC_ENABLE)
);
//
// submit async interrupt transfer
//
EndpointAddr = UsbTouchPanelDevice->IntEndpointDescriptor.EndpointAddress;
PollingInterval = UsbTouchPanelDevice->IntEndpointDescriptor.Interval;
PacketSize = (UINT8)UsbTouchPanelDevice->IntEndpointDescriptor.MaxPacketSize;
if (PacketSize < UsbTouchPanelDevice->ReportFieldInfo.BiggestInputReportGroup->DataSize) {
PacketSize = (UINT8)UsbTouchPanelDevice->ReportFieldInfo.BiggestInputReportGroup->DataSize;
}
Status = UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
EndpointAddr,
TRUE,
PollingInterval,
PacketSize,
OnTouchPanelInterruptComplete,
UsbTouchPanelDevice
);
if (!EFI_ERROR (Status)) {
UsbTouchPanelDevice->ControllerNameTable = NULL;
AddUnicodeString2 (
LANGUAGE_CODE_ENGLISH_ISO639,
gUsbTouchPanelComponentName.SupportedLanguages,
&UsbTouchPanelDevice->ControllerNameTable,
CONTROLLER_DRIVER_NAME,
TRUE
);
AddUnicodeString2 (
LANGUAGE_CODE_ENGLISH_RFC4646,
gUsbTouchPanelComponentName2.SupportedLanguages,
&UsbTouchPanelDevice->ControllerNameTable,
CONTROLLER_DRIVER_NAME,
FALSE
);
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
DisconnectUsbTouchPanel,
(VOID *) Controller,
&gEfiEventLegacyBootGuid,
&LegacyBootEvent
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
DisconnectUsbTouchPanel,
(VOID *) Controller,
&gEfiEventExitBootServicesGuid,
&ExitBootServicesEvent
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
return EFI_SUCCESS;
}
//
// If submit error, uninstall that interface
//
Status = EFI_DEVICE_ERROR;
gBS->UninstallProtocolInterface (
Controller,
&gEfiAbsolutePointerProtocolGuid,
&UsbTouchPanelDevice->AbsolutePointerProtocol
);
ErrorExit:
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (UsbTouchPanelDevice != NULL) {
if ((UsbTouchPanelDevice->AbsolutePointerProtocol).WaitForInput != NULL) {
gBS->CloseEvent ((UsbTouchPanelDevice->AbsolutePointerProtocol).WaitForInput);
}
UsbCore->FreeBuffer (
sizeof (USB_TOUCH_PANEL_DEV),
UsbTouchPanelDevice
);
}
if (LegacyBootEvent != NULL) {
gBS->CloseEvent (LegacyBootEvent);
}
if (ExitBootServicesEvent != NULL) {
gBS->CloseEvent (ExitBootServicesEvent);
}
}
return Status;
}
/**
Stop this driver on ControllerHandle. Support stoping any child handles
created by this driver.
@param This Protocol instance pointer.
@param Controller Handle of device to stop driver on
@param NumberOfChildren Number of Children in the ChildHandleBuffer
@param ChildHandleBuffer List of handles for the children we need to stop.
@retval EFI_SUCCESS
@retval EFI_DEVICE_ERROR
@retval others
**/
EFI_STATUS
EFIAPI
UsbTouchPanelDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice;
EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_CORE_PROTOCOL *UsbCore;
//
// Get our context back.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiAbsolutePointerProtocolGuid,
(VOID **)&AbsolutePointerProtocol,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
UsbTouchPanelDevice = USB_TOUCH_PANEL_DEV_FROM_TOUCH_PANEL_PROTOCOL (AbsolutePointerProtocol);
UsbIo = UsbTouchPanelDevice->UsbIo;
UsbCore = UsbTouchPanelDevice->UsbCore;
//
// Set the UsbIo to NULL to preventing async interrupt transfer restarted
// by recovery handler after deleting the async interrupt transfer
//
UsbTouchPanelDevice->UsbIo = NULL;
gBS->CloseProtocol (
Controller,
&gEfiAbsolutePointerProtocolGuid,
This->DriverBindingHandle,
Controller
);
//
// Remove the recovery handler before deleting the async interrupt transfer to preventing
// async interrupt transfer restarted by recovery handler
//
UsbCore->RemovePeriodicTimer(UsbTouchPanelDevice->RecoveryPollingHandle);
//
// Uninstall the Asyn Interrupt Transfer from this device
// will disable the Touch Panel data input from this device
//
TouchPanelReportStatusCode (
UsbTouchPanelDevice,
EFI_PROGRESS_CODE,
(EFI_PERIPHERAL_TOUCH_PANEL | EFI_P_PC_DISABLE)
);
//
// Delete Touch Panel Async Interrupt Transfer
//
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
UsbTouchPanelDevice->IntEndpointDescriptor.EndpointAddress,
FALSE,
UsbTouchPanelDevice->IntEndpointDescriptor.Interval,
0,
NULL,
NULL
);
gBS->CloseEvent (UsbTouchPanelDevice->AbsolutePointerProtocol.WaitForInput);
Status = gBS->UninstallProtocolInterface (
Controller,
&gEfiAbsolutePointerProtocolGuid,
&UsbTouchPanelDevice->AbsolutePointerProtocol
);
if (EFI_ERROR (Status)) {
return Status;
}
gBS->CloseProtocol (
Controller,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
Controller
);
if (UsbTouchPanelDevice->ControllerNameTable) {
FreeUnicodeStringTable (UsbTouchPanelDevice->ControllerNameTable);
}
UsbCore->FreeBuffer (
sizeof (USB_TOUCH_PANEL_DEV),
UsbTouchPanelDevice
);
return EFI_SUCCESS;
}
/**
Event notification function for disconnect USB Touch Panel
@param Event Legacy Boot event or Exit Boot Service event
@param Context Controller handler of USB Touch Panel
**/
STATIC
VOID
EFIAPI
DisconnectUsbTouchPanel (
IN EFI_EVENT Event,
IN VOID *Context
)
{
gBS->DisconnectController ((EFI_HANDLE) Context, NULL, NULL);
}
/**
Tell if a Usb Controller is a Touch Panel
@param UsbIo Protocol instance pointer.
@retval TRUE It is a Touch Panel
@retval FALSE It is not a Touch Panel
**/
BOOLEAN
IsUsbTouchPanel (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN EFI_USB_CORE_PROTOCOL *UsbCore
)
{
EFI_STATUS Status;
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
EFI_USB_HID_DESCRIPTOR TouchPanelHidDesc;
UINT8 *ReportDesc;
UINT16 DescriptorLength;
BOOLEAN TouchDeviceFound;
REPORT_FIELD_INFO ReportFieldInfo;
UINTN Index;
//
// 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.InterfaceProtocol == PROTOCOL_MOUSE) ||
(InterfaceDescriptor.InterfaceProtocol == PROTOCOL_NONE))) {
Status = UsbCore->UsbGetHidDescriptor (
UsbIo,
InterfaceDescriptor.InterfaceNumber,
&TouchPanelHidDesc
);
if (EFI_ERROR (Status) || (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_NONE && TouchPanelHidDesc.HidClassDesc[0].DescriptorType != 0x22)) {
return FALSE;
}
DescriptorLength = TouchPanelHidDesc.HidClassDesc[0].DescriptorLength;
Status = UsbCore->AllocateBuffer (
DescriptorLength,
ALIGNMENT_32,
(VOID **)&ReportDesc
);
if (EFI_ERROR(Status)) {
return FALSE;
}
TouchDeviceFound = FALSE;
for (Index = 0; Index < 3; Index ++) {
Status = UsbCore->UsbGetReportDescriptor (
UsbIo,
InterfaceDescriptor.InterfaceNumber,
DescriptorLength,
ReportDesc
);
if (!EFI_ERROR (Status)) {
break;
} else if (Status == EFI_DEVICE_ERROR) {
//
// Stall 10ms to waiting for potential signal unstable
//
UsbCore->Stall (10 * 1000);
}
}
if (!EFI_ERROR (Status) &&
!MatchHidDeviceType (ReportDesc, DescriptorLength, TOUCH_PAD_CLASS_CODE) &&
(MatchHidDeviceType (ReportDesc, DescriptorLength, MOUSE_CLASS_CODE) ||
MatchHidDeviceType (ReportDesc, DescriptorLength, POINTER_CLASS_CODE) ||
MatchHidDeviceType (ReportDesc, DescriptorLength, TOUCH_SCREEN_CLASS_CODE) ||
MatchHidDeviceType (ReportDesc, DescriptorLength, PEN_CLASS_CODE))) {
//
// Check the X/Y value type, we only support the absolute value due to it is requirement for AbsolutePointer protocol
//
ZeroMem (&ReportFieldInfo, sizeof (REPORT_FIELD_INFO));
Status = ParseReportDescriptor (
ReportDesc,
DescriptorLength,
&ReportFieldInfo
);
if (EFI_ERROR (Status)) {
return FALSE;
}
//
// Searching for qualified mouse report
//
for (Index = 0; Index < ReportFieldInfo.Total; Index ++) {
if (ReportFieldInfo.ReportGroup[Index].DataValid) {
if ((ReportFieldInfo.ReportGroup[Index].DataAttr == ATTR_MOUSE_INPUT &&
ReportFieldInfo.ReportGroup[Index].Data.Mouse.FieldX.ValueType == ABSOLUTE_VALUE &&
ReportFieldInfo.ReportGroup[Index].Data.Mouse.FieldY.ValueType == ABSOLUTE_VALUE) ||
(ReportFieldInfo.ReportGroup[Index].DataAttr == ATTR_TOUCH_PANEL_INPUT &&
ReportFieldInfo.ReportGroup[Index].Data.TouchPanel.FieldX.ValueType == ABSOLUTE_VALUE &&
ReportFieldInfo.ReportGroup[Index].Data.TouchPanel.FieldY.ValueType == ABSOLUTE_VALUE)) {
TouchDeviceFound = TRUE;
break;
}
}
}
}
UsbCore->FreeBuffer (
DescriptorLength,
ReportDesc
);
if (TouchDeviceFound) return TRUE;
}
return FALSE;
}
EFI_STATUS
SetDeviceMode (
IN USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice
)
{
EFI_STATUS Status;
REPORT_GROUP *ReportGroup;
EFI_USB_CORE_PROTOCOL *UsbCore;
UINT8 *ReportData;
if ((UsbTouchPanelDevice == NULL) ||
(UsbTouchPanelDevice->UsbIo == NULL) ||
(UsbTouchPanelDevice->UsbCore == NULL) ||
(UsbTouchPanelDevice->ReportFieldInfo.DeviceConfigurationReportGroup == NULL)) {
return EFI_INVALID_PARAMETER;
}
ReportGroup = UsbTouchPanelDevice->ReportFieldInfo.DeviceConfigurationReportGroup;
//
// Since Device Configuration must have its own report (see HUTRR34.pdf), Report ID must be
// reported by the USB touch device and can not be the reserved value of 0.
//
if ((ReportGroup->Id == 0) || (!(ReportGroup->DataValid))) {
return EFI_UNSUPPORTED;
}
UsbCore = UsbTouchPanelDevice->UsbCore;
Status = UsbCore->AllocateBuffer (
ReportGroup->DataSize,
ALIGNMENT_32,
(VOID **)&ReportData
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Set Device Mode to single input
//
ReportData[0] = ReportGroup->Id;
Status = SetReportFieldValue (
ReportData,
ReportGroup->DataSize,
&ReportGroup->Data.TouchPanelMode.FieldDeviceMode,
HID_DIGITIZERS_DEVICE_MODE_SINGLE_INPUT
);
if (EFI_ERROR (Status)) {
goto EXIT;
}
if (ReportGroup->Data.TouchPanelMode.FieldDeviceId.DataValid) {
//
// Use a Device ID of 0 to configure all the report groups (i.e. top-level collections)
// at the same time regardless of Device ID (see HUTRR34.pdf).
//
Status = SetReportFieldValue (
ReportData,
ReportGroup->DataSize,
&ReportGroup->Data.TouchPanelMode.FieldDeviceId,
0
);
if (EFI_ERROR (Status)) {
goto EXIT;
}
}
Status = UsbCore->UsbSetReportRequest (
UsbTouchPanelDevice->UsbIo,
UsbTouchPanelDevice->InterfaceDescriptor.InterfaceNumber,
ReportGroup->Id,
HID_FEATURE_REPORT,
ReportGroup->DataSize,
ReportData
);
EXIT:
UsbCore->FreeBuffer (
ReportGroup->DataSize,
ReportData
);
return Status;
}
/**
The workaround for some incompatible device
@param UsbTouchPanelDevice Device instance to be initialized
@retval EFI_SUCCESS Success
@retval EFI_DEVICE_ERROR Init error.
@retval EFI_OUT_OF_RESOURCES Can't allocate memory
**/
STATIC
EFI_STATUS
GetFeatureData (
IN USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice
)
{
EFI_STATUS Status;
EFI_USB_CORE_PROTOCOL *UsbCore;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
UINT8 *FeatureData;
UINT16 *LangIDTable;
UINT16 TableSize;
UINT16 *String;
if (UsbTouchPanelDevice->ReportFieldInfo.FirstFeatureID != 0 && UsbTouchPanelDevice->ReportFieldInfo.MaximumFeatureLength != 0) {
UsbIo = UsbTouchPanelDevice->UsbIo;
UsbCore = UsbTouchPanelDevice->UsbCore;
Status = UsbIo->UsbGetDeviceDescriptor (
UsbIo,
&DeviceDescriptor
);
if (EFI_ERROR (Status)) {
return Status;
}
if (DeviceDescriptor.StrProduct != 0) {
Status = UsbCore->AllocateBuffer (
UsbTouchPanelDevice->ReportFieldInfo.MaximumFeatureLength,
ALIGNMENT_32,
(VOID **)&FeatureData
);
if (EFI_ERROR (Status)) {
return Status;
}
UsbCore->UsbGetReportRequest (
UsbIo,
UsbTouchPanelDevice->InterfaceDescriptor.InterfaceNumber,
(UINT8)UsbTouchPanelDevice->ReportFieldInfo.FirstFeatureID,
HID_FEATURE_REPORT,
(UINT16)UsbTouchPanelDevice->ReportFieldInfo.MaximumFeatureLength,
FeatureData
);
Status = UsbIo->UsbGetSupportedLanguages (
UsbIo,
&LangIDTable,
&TableSize
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
UsbCore->UsbGetReportRequest (
UsbIo,
UsbTouchPanelDevice->InterfaceDescriptor.InterfaceNumber,
(UINT8)UsbTouchPanelDevice->ReportFieldInfo.FirstFeatureID,
HID_FEATURE_REPORT,
(UINT16)UsbTouchPanelDevice->ReportFieldInfo.MaximumFeatureLength,
FeatureData
);
UsbIo->UsbGetStringDescriptor (
UsbIo,
LangIDTable[0],
DeviceDescriptor.StrProduct,
&String
);
ErrorExit:
UsbCore->FreeBuffer (
UsbTouchPanelDevice->ReportFieldInfo.MaximumFeatureLength,
FeatureData
);
}
}
return EFI_SUCCESS;
}
/**
Initialize the Usb Touch Panel Device.
@param UsbTouchPanelDevice Device instance to be initialized
@retval EFI_SUCCESS Success
@retval EFI_DEVICE_ERROR Init error.
@retval EFI_OUT_OF_RESOURCES Can't allocate memory
**/
STATIC
EFI_STATUS
InitializeUsbTouchPanelDevice (
IN USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice
)
{
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_CORE_PROTOCOL *UsbCore;
EFI_STATUS Status;
EFI_USB_HID_DESCRIPTOR TouchPanelHidDesc;
UINT8 *ReportDesc;
REPORT_GROUP *ReportGroup;
UsbIo = UsbTouchPanelDevice->UsbIo;
UsbCore = UsbTouchPanelDevice->UsbCore;
//
// Get HID descriptor
//
Status = UsbCore->UsbGetHidDescriptor (
UsbIo,
UsbTouchPanelDevice->InterfaceDescriptor.InterfaceNumber,
&TouchPanelHidDesc
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get Report descriptor
//
if (TouchPanelHidDesc.HidClassDesc[0].DescriptorType != 0x22) {
return EFI_UNSUPPORTED;
}
Status = UsbCore->AllocateBuffer (
TouchPanelHidDesc.HidClassDesc[0].DescriptorLength,
ALIGNMENT_32,
(VOID **)&ReportDesc
);
if (EFI_ERROR(Status)) {
return EFI_OUT_OF_RESOURCES;
}
Status = UsbCore->UsbGetReportDescriptor (
UsbIo,
UsbTouchPanelDevice->InterfaceDescriptor.InterfaceNumber,
TouchPanelHidDesc.HidClassDesc[0].DescriptorLength,
ReportDesc
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Initialize with "not found" values before parsing.
//
UsbTouchPanelDevice->ReportFieldInfo.BiggestInputReportGroup = NULL;
UsbTouchPanelDevice->ReportFieldInfo.DeviceConfigurationReportGroup = NULL;
//
// Parse report descriptor
//
Status = ParseReportDescriptor (
ReportDesc,
TouchPanelHidDesc.HidClassDesc[0].DescriptorLength,
&UsbTouchPanelDevice->ReportFieldInfo
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Since we do not know which report data will be sent by the USB device (and we will interpret
// the different report data by the report group with the correct Report ID anyway), the default
// Mode parameters are set based on the report group with the biggest input data size for now.
//
ReportGroup = UsbTouchPanelDevice->ReportFieldInfo.BiggestInputReportGroup;
if ((ReportGroup == NULL) ||
(!(ReportGroup->DataValid)) ||
(ReportGroup->DataSize == 0)) {
Status = EFI_UNSUPPORTED;
goto ErrorExit;
}
UsbTouchPanelDevice->ReportId = ReportGroup->Id;
UsbTouchPanelDevice->Mode.AbsoluteMinX = ReportGroup->Data.TouchPanel.FieldX.Min;
UsbTouchPanelDevice->Mode.AbsoluteMinY = ReportGroup->Data.TouchPanel.FieldY.Min;
UsbTouchPanelDevice->Mode.AbsoluteMaxX = ReportGroup->Data.TouchPanel.FieldX.Max;
UsbTouchPanelDevice->Mode.AbsoluteMaxY = ReportGroup->Data.TouchPanel.FieldY.Max;
UsbTouchPanelDevice->Mode.Attributes = 0;
if (ReportGroup->Data.TouchPanel.FieldAltActive.DataValid) {
UsbTouchPanelDevice->Mode.Attributes |= EFI_ABSP_SupportsAltActive;
}
//
// Set indefinite Idle rate for USB Touch Panel
//
UsbCore->UsbSetIdleRequest (
UsbIo,
UsbTouchPanelDevice->InterfaceDescriptor.InterfaceNumber,
0,
0
);
//
// If Device Configuration feature report is found, this touch device has multiple operating
// modes (mouse, single-input, multi-input, etc.). Some devices only send "correct" report data
// (i.e. absolute coordinates for digitizer as opposed to relative displacements for mouse) when
// they are operating in single-input mode. However, some other devices do not change operating
// mode after SetDeviceMode (), but can still work with their report data; thus, we do not check
// the return status of SetDeviceMode ().
//
if (UsbTouchPanelDevice->ReportFieldInfo.DeviceConfigurationReportGroup != NULL) {
SetDeviceMode (UsbTouchPanelDevice);
}
//
// Some incompatible device will postpone the first event around 10 seconds. To launch GetFeature
// command twice with first feature report ID and maximum feature length, and launch GetString to
// get vendor string to workaround this issue
//
GetFeatureData (UsbTouchPanelDevice);
if (UsbTouchPanelDevice->RecoveryPollingHandle) {
UsbCore->RemovePeriodicTimer(UsbTouchPanelDevice->RecoveryPollingHandle);
UsbTouchPanelDevice->RecoveryPollingHandle = NULL;
}
ErrorExit:
UsbCore->FreeBuffer (
TouchPanelHidDesc.HidClassDesc[0].DescriptorLength,
ReportDesc
);
return Status;
}
/**
It is called whenever there is data received from async interrupt
transfer.
@param Data Data received.
@param DataLength Length of Data
@param Context Passed in context
@param Result Async Interrupt Transfer result
@retval EFI_SUCCESS
@retval EFI_DEVICE_ERROR
**/
STATIC
EFI_STATUS
EFIAPI
OnTouchPanelInterruptComplete (
IN VOID *Data,
IN UINTN DataLength,
IN VOID *Context,
IN UINT32 Result
)
{
USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_CORE_PROTOCOL *UsbCore;
UINT8 EndpointAddr;
UINT32 UsbResult;
UINTN Mode;
REPORT_GROUP *ReportGroup;
UINTN Index;
EFI_ABSOLUTE_POINTER_STATE AbsPtrState;
UINTN BufferIn;
UsbTouchPanelDevice = (USB_TOUCH_PANEL_DEV *) Context;
UsbIo = UsbTouchPanelDevice->UsbIo;
UsbCore = UsbTouchPanelDevice->UsbCore;
if (UsbIo == NULL) return EFI_DEVICE_ERROR;
//
// Get current mode
//
UsbCore->GetMode(&Mode);
//
// Analyzes the Result and performs corresponding action.
//
if (Result != EFI_USB_NOERROR) {
//
// Some errors happen during the process
//
TouchPanelReportStatusCode (
UsbTouchPanelDevice,
EFI_ERROR_CODE | EFI_ERROR_MINOR,
(EFI_PERIPHERAL_TOUCH_PANEL | EFI_P_EC_INPUT_ERROR)
);
if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
EndpointAddr = UsbTouchPanelDevice->IntEndpointDescriptor.EndpointAddress;
UsbCore->UsbClearEndpointHalt (
UsbIo,
EndpointAddr,
&UsbResult
);
}
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
UsbTouchPanelDevice->IntEndpointDescriptor.EndpointAddress,
FALSE,
0,
0,
NULL,
NULL
);
//
// Check is the device be detached
//
if (UsbCore->CheckDeviceDetached(UsbIo) == EFI_SUCCESS) {
return EFI_DEVICE_ERROR;
}
UsbCore->InsertPeriodicTimer(
USB_CORE_ONCE_TIMER,
UsbTouchPanelRecoveryHandler,
UsbTouchPanelDevice,
EFI_USB_INTERRUPT_DELAY / 10000,
&UsbTouchPanelDevice->RecoveryPollingHandle
);
return EFI_DEVICE_ERROR;
}
if (DataLength == 0 || Data == NULL) {
return EFI_SUCCESS;
}
if (Mode != USB_CORE_RUNTIME_MODE) {
//
// USB Device Class Definition for Human Interface Devices (HID) specification version 1.11
// page 36 states that a Report ID value of 0 is reserved. However, since Report ID is
// optional, our saved value of Report ID can be 0 and it means that no Report ID item tags
// were present in the report descriptor. If no Report ID was declared, we assume only one
// report group exists and continue using the first report group (see page 18 of above
// specification).
//
if (UsbTouchPanelDevice->ReportId == 0) {
ReportGroup = &(UsbTouchPanelDevice->ReportFieldInfo.ReportGroup[0]);
} else {
ReportGroup = NULL;
for (Index = 0; Index < UsbTouchPanelDevice->ReportFieldInfo.Total; Index++) {
if ((UsbTouchPanelDevice->ReportFieldInfo.ReportGroup[Index].Id == (*(UINT8*)Data)) &&
(UsbTouchPanelDevice->ReportFieldInfo.ReportGroup[Index].DataValid)) {
ReportGroup = &UsbTouchPanelDevice->ReportFieldInfo.ReportGroup[Index];
break;
}
}
if (!ReportGroup) return EFI_NOT_FOUND;
if (UsbTouchPanelDevice->ReportId != ReportGroup->Id) {
//
// Reset the Mode parameters due to report ID changed
//
UsbTouchPanelDevice->ReportId = ReportGroup->Id;
//
// Set limit by report descriptor
//
UsbTouchPanelDevice->Mode.AbsoluteMinX = ReportGroup->Data.TouchPanel.FieldX.Min;
UsbTouchPanelDevice->Mode.AbsoluteMinY = ReportGroup->Data.TouchPanel.FieldY.Min;
UsbTouchPanelDevice->Mode.AbsoluteMaxX = ReportGroup->Data.TouchPanel.FieldX.Max;
UsbTouchPanelDevice->Mode.AbsoluteMaxY = ReportGroup->Data.TouchPanel.FieldY.Max;
UsbTouchPanelDevice->Mode.Attributes = 0;
if (ReportGroup->Data.TouchPanel.FieldAltActive.DataValid) {
UsbTouchPanelDevice->Mode.Attributes |= EFI_ABSP_SupportsAltActive;
}
}
}
if (DataLength < ReportGroup->DataSize) {
//
// Partial packet data is not allowed
//
return EFI_NOT_FOUND;
}
if (ReportGroup->Data.TouchPanel.FieldContactCount.DataValid &&
GetReportFieldValue (Data, DataLength, &ReportGroup->Data.TouchPanel.FieldContactCount) == 0) {
//
// Dummy input data, keep the previous position but clear the button states
//
AbsPtrState.CurrentX = UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].CurrentX;
AbsPtrState.CurrentY = UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].CurrentY;
AbsPtrState.CurrentZ = 0;
AbsPtrState.ActiveButtons = 0;
} else {
//
// Got input data, renew the position and button states
//
AbsPtrState.CurrentX = (UINT32) GetReportFieldValue (Data, DataLength, &ReportGroup->Data.TouchPanel.FieldX);
AbsPtrState.CurrentY = (UINT32) GetReportFieldValue (Data, DataLength, &ReportGroup->Data.TouchPanel.FieldY);
AbsPtrState.CurrentZ = 0;
AbsPtrState.ActiveButtons = 0;
if (GetReportFieldValue (Data, DataLength, &ReportGroup->Data.TouchPanel.FieldTouchActive)) {
AbsPtrState.ActiveButtons |= EFI_ABSP_TouchActive;
}
if (GetReportFieldValue (Data, DataLength, &ReportGroup->Data.TouchPanel.FieldAltActive)) {
AbsPtrState.ActiveButtons |= EFI_ABS_AltActive;
}
}
UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].CurrentX = AbsPtrState.CurrentX;
UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].CurrentY = AbsPtrState.CurrentY;
UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].CurrentZ = AbsPtrState.CurrentZ;
if ((UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].ActiveButtons != 0) || (AbsPtrState.ActiveButtons != 0)) {
UsbTouchPanelDevice->StateChanged = TRUE;
if (UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].ActiveButtons != AbsPtrState.ActiveButtons) {
UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn].ActiveButtons = AbsPtrState.ActiveButtons;
//
// Advance the internal buffer only when button state changed to reduce the dragging phenomenon
//
BufferIn = UsbTouchPanelDevice->BufferIn + 1;
if (BufferIn == STATE_BUFFER_SIZE) BufferIn = 0;
if (BufferIn != UsbTouchPanelDevice->BufferOut) {
//
// Copy last state to new position for use of check procedure of last button state
//
CopyMem (
&UsbTouchPanelDevice->State[BufferIn],
&UsbTouchPanelDevice->State[UsbTouchPanelDevice->BufferIn],
sizeof (EFI_ABSOLUTE_POINTER_STATE)
);
UsbTouchPanelDevice->BufferIn = BufferIn;
}
}
}
}
return EFI_SUCCESS;
}
/**
Get the Touch Panel state, see ABSOLUTE POINTER PROTOCOL.
@param This Protocol instance pointer.
@param Touch PanelState Current Touch Panel state
@retval EFI_SUCCESS
@retval EFI_DEVICE_ERROR
@retval EFI_NOT_READY
**/
STATIC
EFI_STATUS
EFIAPI
GetTouchPanelState (
IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
OUT EFI_ABSOLUTE_POINTER_STATE *TouchPanelState
)
{
USB_TOUCH_PANEL_DEV *TouchPanelDev;
if (TouchPanelState == NULL) {
return EFI_DEVICE_ERROR;
}
TouchPanelDev = USB_TOUCH_PANEL_DEV_FROM_TOUCH_PANEL_PROTOCOL (This);
if (!TouchPanelDev->StateChanged) {
return EFI_NOT_READY;
}
CopyMem (
TouchPanelState,
&TouchPanelDev->State[TouchPanelDev->BufferOut],
sizeof (EFI_ABSOLUTE_POINTER_STATE)
);
if (TouchPanelDev->BufferOut != TouchPanelDev->BufferIn) {
TouchPanelDev->BufferOut ++;
if (TouchPanelDev->BufferOut == STATE_BUFFER_SIZE) TouchPanelDev->BufferOut = 0;
}
if (TouchPanelDev->BufferOut == TouchPanelDev->BufferIn) {
TouchPanelDev->StateChanged = FALSE;
}
return EFI_SUCCESS;
}
/**
Reset the Touch Panel device, see ABSOLUTE POINTER PROTOCOL.
@param This Protocol instance pointer.
@param ExtendedVerification Ignored here
@retval EFI_SUCCESS
**/
STATIC
EFI_STATUS
EFIAPI
UsbTouchPanelReset (
IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice;
EFI_USB_IO_PROTOCOL *UsbIo;
UsbTouchPanelDevice = USB_TOUCH_PANEL_DEV_FROM_TOUCH_PANEL_PROTOCOL (This);
UsbIo = UsbTouchPanelDevice->UsbIo;
TouchPanelReportStatusCode (
UsbTouchPanelDevice,
EFI_PROGRESS_CODE,
(EFI_PERIPHERAL_TOUCH_PANEL | EFI_P_PC_RESET)
);
ZeroMem (
UsbTouchPanelDevice->State,
sizeof (EFI_ABSOLUTE_POINTER_STATE) * STATE_BUFFER_SIZE
);
UsbTouchPanelDevice->StateChanged = FALSE;
UsbTouchPanelDevice->BufferIn = 0;
UsbTouchPanelDevice->BufferOut = 0;
return EFI_SUCCESS;
}
/**
Event notification function for ABSOLUTE_POINTER.WaitForInput event
Signal the event if there is input from Touch Panel
@param Event Wait Event
@param Context Passed parameter to event handler
**/
STATIC
VOID
EFIAPI
UsbTouchPanelWaitForInput (
IN EFI_EVENT Event,
IN VOID *Context
)
{
USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice;
UsbTouchPanelDevice = (USB_TOUCH_PANEL_DEV *) Context;
//
// Someone is waiting on the TouchPanel event, if there's
// input from Touch Panel, signal the event
//
if (UsbTouchPanelDevice->StateChanged) {
gBS->SignalEvent (Event);
}
}
/**
Timer handler for Delayed Recovery timer.
@param Event The Delayed Recovery event.
@param Context Points to the USB_KB_DEV instance.
**/
STATIC
VOID
EFIAPI
UsbTouchPanelRecoveryHandler (
IN UINTN Event,
IN VOID *Context
)
{
USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT8 PacketSize;
UsbTouchPanelDevice = (USB_TOUCH_PANEL_DEV *) Context;
UsbTouchPanelDevice->RecoveryPollingHandle = NULL;
UsbIo = UsbTouchPanelDevice->UsbIo;
if (UsbIo == NULL) return;
PacketSize = (UINT8)UsbTouchPanelDevice->IntEndpointDescriptor.MaxPacketSize;
if (PacketSize < UsbTouchPanelDevice->ReportFieldInfo.BiggestInputReportGroup->DataSize) {
PacketSize = (UINT8)UsbTouchPanelDevice->ReportFieldInfo.BiggestInputReportGroup->DataSize;
}
UsbIo->UsbAsyncInterruptTransfer (
UsbIo,
UsbTouchPanelDevice->IntEndpointDescriptor.EndpointAddress,
TRUE,
UsbTouchPanelDevice->IntEndpointDescriptor.Interval,
PacketSize,
OnTouchPanelInterruptComplete,
UsbTouchPanelDevice
);
}
/**
Report Status Code in Usb Bot Driver
@param DevicePath Use this to get Device Path
@param CodeType Status Code Type
@param CodeValue Status Code Value
**/
STATIC
VOID
TouchPanelReportStatusCode (
IN USB_TOUCH_PANEL_DEV *UsbTouchPanelDevice,
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value
)
{
UINTN Mode;
BOOLEAN InSmm;
UsbTouchPanelDevice->UsbCore->GetMode(&Mode);
if (Mode != USB_CORE_RUNTIME_MODE) {
//
// Only report status code during POST and non-SMM mode
//
UsbTouchPanelDevice->UsbCore->IsInSmm(&InSmm);
if (!InSmm) {
ReportStatusCodeWithDevicePath (
CodeType,
Value,
UsbTouchPanelDevice->DevicePath
);
}
}
}