/**
|
* @file UsbTransfer.c
|
* @brief Wrapper of UEFI USB bulk and control transfer interface for USB DisplayLink driver.
|
*
|
* Copyright (c) 2018-2019, DisplayLink (UK) Ltd. All rights reserved.
|
*
|
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
*
|
**/
|
|
#include "UsbDisplayLink.h"
|
|
/**
|
* Write the data to the DisplayLink device using the USBIO protocol.
|
* @param UsbDisplayLinkDev
|
* @param Buffer
|
* @param DataLen
|
* @param USBStatus
|
* @return
|
* EFI_SUCCESS The bulk transfer has been successfully executed.
|
* EFI_INVALID_PARAMETER If DeviceEndpoint is not valid.
|
* EFI_INVALID_PARAMETER Data is NULL.
|
* EFI_INVALID_PARAMETER DataLength is NULL.
|
* EFI_INVALID_PARAMETER Status is NULL.
|
* EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
* EFI_TIMEOUT The bulk transfer cannot be completed within Timeout timeframe.
|
* EFI_DEVICE_ERROR The transfer failed other than timeout, and the transfer status is returned in Status.
|
*/
|
EFI_STATUS
|
DlUsbBulkWrite (
|
IN USB_DISPLAYLINK_DEV* UsbDisplayLinkDev,
|
IN CONST UINT8* Buffer,
|
IN UINTN DataLen,
|
OUT UINT32 *USBStatus
|
)
|
{
|
EFI_STATUS Status;
|
Status = UsbDisplayLinkDev->UsbIo->UsbBulkTransfer (
|
UsbDisplayLinkDev->UsbIo,
|
UsbDisplayLinkDev->BulkOutEndpointDescriptor.EndpointAddress,
|
(VOID*)Buffer,
|
&DataLen,
|
DISPLAYLINK_USB_BULK_TIMEOUT,
|
USBStatus);
|
|
return Status;
|
}
|
|
/**
|
* Read data from the DisplayLink device using the USBIO protocol.
|
* @param UsbDisplayLinkDev
|
* @param Buffer
|
* @param BufferLen
|
* @return 0 if an error occurred or 0 bytes were read, otherwise the number of bytes read
|
*/
|
UINTN
|
DlUsbBulkRead (
|
IN USB_DISPLAYLINK_DEV* UsbDisplayLinkDev,
|
IN UINT8* Buffer,
|
IN UINTN BufferLen
|
)
|
{
|
UINT32 Result;
|
UINTN ReadLen;
|
EFI_STATUS Status;
|
|
ReadLen = BufferLen;
|
|
Status = UsbDisplayLinkDev->UsbIo->UsbBulkTransfer (
|
UsbDisplayLinkDev->UsbIo,
|
UsbDisplayLinkDev->BulkInEndpointDescriptor.EndpointAddress,
|
Buffer,
|
&ReadLen,
|
DISPLAYLINK_USB_BULK_TIMEOUT,
|
&Result);
|
|
if (EFI_ERROR (Status)) {
|
return 0;
|
}
|
|
return ReadLen;
|
}
|
|
|
/**
|
Send a control message (e.g set video mode) message to the DisplayLink device.
|
|
@param Device USB device handle.
|
@param request Request type, e.g. SET_VIDEO_MODE
|
@param value
|
@param controlMsg Pointer to the message to send.
|
@param controlMsgLen Length of the message.
|
|
@retval EFI_SUCCESS Successfully sent message.
|
|
**/
|
EFI_STATUS
|
DlUsbSendControlWriteMessage (
|
IN USB_DISPLAYLINK_DEV *Device,
|
IN UINT8 Request,
|
IN UINT16 Value,
|
IN CONST VOID *ControlMsg,
|
IN UINT16 ControlMsgLen
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 UsbStatus;
|
EFI_USB_DEVICE_REQUEST UsbRequest;
|
|
ZeroMem (&UsbRequest, sizeof (UsbRequest));
|
UsbRequest.RequestType = USB_REQ_TYPE_VENDOR | USB_TARGET_INTERFACE;
|
UsbRequest.Index = Device->InterfaceDescriptor.InterfaceNumber;
|
UsbRequest.Request = Request;
|
UsbRequest.Value = Value;
|
UsbRequest.Length = ControlMsgLen;
|
|
Status = Device->UsbIo->UsbControlTransfer (
|
Device->UsbIo,
|
&UsbRequest,
|
EfiUsbDataOut,
|
DISPLAYLINK_USB_CTRL_TIMEOUT,
|
(VOID *)ControlMsg,
|
ControlMsgLen,
|
&UsbStatus);
|
|
if (EFI_ERROR (Status)) {
|
DEBUG ((DEBUG_ERROR, "USB write control transfer failed - %r (USB status x%x).\n", Status, UsbStatus));
|
Status = EFI_DEVICE_ERROR;
|
}
|
return Status;
|
}
|
|
|
/**
|
Request data from the DisplayLink device (e.g. the monitor EDID)
|
|
@param Device USB device handle.
|
@param request Request type, e.g. GET_OUTPUT_EDID
|
@param value
|
@param controlMsg Pointer to the message to send.
|
@param controlMsgLen Length of the message.
|
|
@retval EFI_SUCCESS Successfully sent message.
|
|
**/
|
EFI_STATUS
|
DlUsbSendControlReadMessage (
|
IN USB_DISPLAYLINK_DEV *Device,
|
IN UINT8 Request,
|
IN UINT16 Value,
|
OUT VOID *ControlMsg,
|
IN UINT16 ControlMsgLen
|
)
|
{
|
EFI_STATUS Status;
|
UINT32 UsbStatus;
|
EFI_USB_DEVICE_REQUEST UsbRequest;
|
|
ZeroMem (&UsbRequest, sizeof (UsbRequest));
|
UsbRequest.RequestType = USB_REQ_TYPE_VENDOR | USB_TARGET_INTERFACE | USB_ENDPOINT_DIR_IN;
|
UsbRequest.Request = Request;
|
UsbRequest.Value = Value;
|
UsbRequest.Index = Device->InterfaceDescriptor.InterfaceNumber;
|
UsbRequest.Length = ControlMsgLen;
|
|
Status = Device->UsbIo->UsbControlTransfer (
|
Device->UsbIo,
|
&UsbRequest,
|
EfiUsbDataIn,
|
DISPLAYLINK_USB_CTRL_TIMEOUT,
|
(VOID *)ControlMsg,
|
ControlMsgLen,
|
&UsbStatus);
|
|
if (EFI_ERROR (Status)) {
|
DEBUG ((DEBUG_ERROR, "USB read control transfer failed - %r (USB status x%x).\n", Status, UsbStatus));
|
Status = EFI_DEVICE_ERROR;
|
}
|
return Status;
|
}
|