summaryrefslogtreecommitdiff
path: root/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c')
-rw-r--r--OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c2586
1 files changed, 0 insertions, 2586 deletions
diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c
deleted file mode 100644
index c03606b20b..0000000000
--- a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c
+++ /dev/null
@@ -1,2586 +0,0 @@
-/** @file
- USB Serial Driver that manages USB to Serial and produces Serial IO Protocol.
-
-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
-Portions Copyright 2012 Ashley DeSimone
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD
-License which accompanies this distribution. The full text of the license may
-be found at http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-//
-
-// Tested with VEND_ID 0x0403, DEVICE_ID 0x6001
-//
-// Driver starts the device with the following values:
-// 115200, No parity, 8 data bits, 1 stop bit, No Flow control
-//
-
-#include "FtdiUsbSerialDriver.h"
-
-//
-// Table of supported devices. This is the device information that this
-// driver was developed with. Add other FTDI devices as needed.
-//
-USB_DEVICE gUSBDeviceList[] = {
- {VID_FTDI, DID_FTDI_FT232},
- {0,0}
-};
-
-//
-// USB Serial Driver Global Variables
-//
-EFI_DRIVER_BINDING_PROTOCOL gUsbSerialDriverBinding = {
- UsbSerialDriverBindingSupported,
- UsbSerialDriverBindingStart,
- UsbSerialDriverBindingStop,
- 0xa,
- NULL,
- NULL
-};
-
-//
-// Table with the nearest power of 2 for the numbers 0-15
-//
-UINT8 gRoundedPowersOf2[16] = { 0, 2, 2, 4, 4, 4, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16 };
-
-/**
- Check to see if the device path node is the Flow control node
-
- @param[in] FlowControl The device path node to be checked
-
- @retval TRUE It is the flow control node
- @retval FALSE It is not the flow control node
-
-**/
-BOOLEAN
-IsUartFlowControlNode (
- IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
- )
-{
- return (BOOLEAN) (
- (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
- (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
- );
-}
-
-/**
- Checks the device path to see if it contains flow control.
-
- @param[in] DevicePath The device path to be checked
-
- @retval TRUE It contains flow control
- @retval FALSE It does not contain flow control
-
-**/
-BOOLEAN
-ContainsFlowControl (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- while (!IsDevicePathEnd (DevicePath)) {
- if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
- return TRUE;
- }
- DevicePath = NextDevicePathNode (DevicePath);
- }
- return FALSE;
-}
-
-/**
- Transfer the data between the device and host.
-
- This function transfers the data between the device and host.
- BOT transfer is composed of three phases: Command, Data, and Status.
- This is the Data phase.
-
- @param UsbBot[in] The USB BOT device
- @param DataDir[in] The direction of the data
- @param Data[in, out] The buffer to hold data
- @param TransLen[in, out] The expected length of the data
- @param Timeout[in] The time to wait the command to complete
-
- @retval EFI_SUCCESS The data is transferred
- @retval EFI_SUCCESS No data to transfer
- @retval EFI_NOT_READY The device return NAK to the transfer
- @retval Others Failed to transfer data
-
-**/
-EFI_STATUS
-UsbSerialDataTransfer (
- IN USB_SER_DEV *UsbBot,
- IN EFI_USB_DATA_DIRECTION DataDir,
- IN OUT VOID *Data,
- IN OUT UINTN *TransLen,
- IN UINT32 Timeout
- )
-{
- EFI_USB_ENDPOINT_DESCRIPTOR *Endpoint;
- EFI_STATUS Status;
- UINT32 Result;
-
- //
- // If no data to transfer, just return EFI_SUCCESS.
- //
- if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
- return EFI_SUCCESS;
- }
-
- //
- // Select the endpoint then issue the transfer
- //
- if (DataDir == EfiUsbDataIn) {
- Endpoint = &UsbBot->InEndpointDescriptor;
- } else {
- Endpoint = &UsbBot->OutEndpointDescriptor;
- }
-
- Result = 0;
- Status = UsbBot->UsbIo->UsbBulkTransfer (
- UsbBot->UsbIo,
- Endpoint->EndpointAddress,
- Data,
- TransLen,
- Timeout,
- &Result
- );
- if (EFI_ERROR (Status)) {
- if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {
- Status = EFI_NOT_READY;
- } else {
- UsbBot->Shutdown = TRUE; // Fixes infinite loop in older EFI
- }
- return Status;
- }
- return Status;
-}
-
-/**
- Sets the status values of the Usb Serial Device.
-
- @param UsbSerialDevice[in] Handle to the Usb Serial Device to set the status
- for
- @param StatusBuffer[in] Buffer holding the status values
-
- @retval EFI_SUCCESS The status values were read and set correctly
-
-**/
-EFI_STATUS
-EFIAPI
-SetStatusInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- IN UINT8 *StatusBuffer
- )
-{
- UINT8 Msr;
-
- Msr = (StatusBuffer[0] & MSR_MASK);
-
- //
- // set the Status values to disabled
- //
- UsbSerialDevice->StatusValues.CtsState = FALSE;
- UsbSerialDevice->StatusValues.DsrState = FALSE;
- UsbSerialDevice->StatusValues.RiState = FALSE;
- UsbSerialDevice->StatusValues.SdState = FALSE;
-
- //
- // Check the values from the status buffer and set the appropriate status
- // values to enabled
- //
- if ((Msr & CTS_MASK) == CTS_MASK) {
- UsbSerialDevice->StatusValues.CtsState = TRUE;
- }
- if ((Msr & DSR_MASK) == DSR_MASK) {
- UsbSerialDevice->StatusValues.DsrState = TRUE;
- }
- if ((Msr & RI_MASK) == RI_MASK) {
- UsbSerialDevice->StatusValues.RiState = TRUE;
- }
- if ((Msr & SD_MASK) == SD_MASK) {
- UsbSerialDevice->StatusValues.SdState = TRUE;
- }
- return EFI_SUCCESS;
-}
-
-/**
- Initiates a read operation on the Usb Serial Device.
-
- @param UsbSerialDevice[in] Handle to the USB device to read
- @param BufferSize[in, out] On input, the size of the Buffer. On output,
- the amount of data returned in Buffer.
- Setting this to zero will initiate a read
- and store all data returned in the internal
- buffer.
- @param Buffer [out] The buffer to return the data into.
-
- @retval EFI_SUCCESS The data was read.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_TIMEOUT The data write was stopped due to a timeout.
-
-**/
-EFI_STATUS
-EFIAPI
-ReadDataFromUsb (
- IN USB_SER_DEV *UsbSerialDevice,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINTN ReadBufferSize;
- UINT8 *ReadBuffer;
- UINTN Index;
- EFI_TPL Tpl;
- UINT8 StatusBuffer[2]; // buffer to store the status bytes
-
- ReadBufferSize = 512;
- ReadBuffer = &(UsbSerialDevice->ReadBuffer[0]);
-
- if (UsbSerialDevice->Shutdown) {
- return EFI_DEVICE_ERROR;
- }
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- Status = UsbSerialDataTransfer (
- UsbSerialDevice,
- EfiUsbDataIn,
- ReadBuffer,
- &ReadBufferSize,
- FTDI_TIMEOUT*2 //Padded because timers won't be exactly aligned
- );
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- if (Status == EFI_TIMEOUT) {
- return EFI_TIMEOUT;
- } else {
- return EFI_DEVICE_ERROR;
- }
- }
-
- //
- // Store the status bytes in the status buffer
- //
- for (Index = 0; Index < 2; Index++) {//only the first 2 bytes are status bytes
- StatusBuffer[Index] = ReadBuffer[Index];
- }
- //
- // update the statusvalue field of the usbserialdevice
- //
- Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);
- if (Status != EFI_SUCCESS) {
- }
-
- //
- // Store the read data in the read buffer, start at 2 to ignore status bytes
- //
- for (Index = 2; Index < ReadBufferSize; Index++) {
- if (((UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH) == UsbSerialDevice->DataBufferHead) {
- break;
- }
- if (ReadBuffer[Index] == 0x00) {
- //
- // This is null, do not add
- //
- } else {
- UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferTail] = ReadBuffer[Index];
- UsbSerialDevice->DataBufferTail = (UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH;
- }
- }
-
- //
- // Read characters out of the buffer to satisfy caller's request.
- //
- for (Index = 0; Index < *BufferSize; Index++) {
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- break;
- }
- //
- // Still have characters in the buffer to return
- //
- ((UINT8 *)Buffer)[Index] = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];
- UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;
- }
- //
- // Return actual number of bytes returned.
- //
- *BufferSize = Index;
- gBS->RestoreTPL (Tpl);
- return EFI_SUCCESS;
-}
-
-/**
- Sets the initial status values of the Usb Serial Device by reading the status
- bytes from the device.
-
- @param UsbSerialDevice[in] Handle to the Usb Serial Device that needs its
- initial status values set
-
- @retval EFI_SUCCESS The status bytes were read successfully and the
- initial status values were set correctly
- @retval EFI_TIMEOUT The read of the status bytes was stopped due to a
- timeout
- @retval EFI_DEVICE_ERROR The device reported an error during the read of
- the status bytes
-
-**/
-EFI_STATUS
-EFIAPI
-SetInitialStatus (
- IN USB_SER_DEV *UsbSerialDevice
- )
-{
- EFI_STATUS Status;
- UINTN BufferSize;
- EFI_TPL Tpl;
- UINT8 StatusBuffer[2];
-
- Status = EFI_UNSUPPORTED;
- BufferSize = sizeof (StatusBuffer);
-
- if (UsbSerialDevice->Shutdown) {
- return EFI_DEVICE_ERROR;
- }
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- Status = UsbSerialDataTransfer (
- UsbSerialDevice,
- EfiUsbDataIn,
- StatusBuffer,
- &BufferSize,
- 40 //Slightly more than 2x the FTDI polling frequency to make sure that data will be returned
- );
-
- Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);
-
- gBS->RestoreTPL (Tpl);
-
- return Status;
-}
-
-/**
- UsbSerialDriverCheckInput.
- attempts to read data in from the device periodically, stores any read data
- and updates the control attributes.
-
- @param Event[in]
- @param Context[in]....The current instance of the USB serial device
-
-**/
-VOID
-EFIAPI
-UsbSerialDriverCheckInput (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- UINTN BufferSize;
- USB_SER_DEV *UsbSerialDevice;
-
- UsbSerialDevice = (USB_SER_DEV*)Context;
-
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- //
- // Data buffer is empty, try to read from device
- //
- BufferSize = 0;
- ReadDataFromUsb (UsbSerialDevice, &BufferSize, NULL);
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- //
- // Data buffer still has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY
- // flag
- //
- UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
- } else {
- //
- // Read has returned some data, clear the EFI_SERIAL_INPUT_BUFFER_EMPTY
- // flag
- //
- UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
- }
- } else {
- //
- // Data buffer has data, no read attempt required
- //
- UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
- }
-}
-
-/**
- Encodes the baud rate into the format expected by the Ftdi device.
-
- @param BaudRate[in] The baudrate to be set on the device
- @param EncodedBaudRate[out] The baud rate encoded in the format
- expected by the Ftdi device
-
- @return EFI_SUCCESS Baudrate encoding was calculated
- successfully
- @return EFI_INVALID_PARAMETER An invalid value of BaudRate was received
-
-**/
-EFI_STATUS
-EFIAPI
-EncodeBaudRateForFtdi (
- IN UINT64 BaudRate,
- OUT UINT16 *EncodedBaudRate
- )
-{
- UINT32 Divisor;
- UINT32 AdjustedFrequency;
- UINT16 Result;
-
- //
- // Check to make sure we won't get an integer overflow
- //
- if ((BaudRate < 178) || ( BaudRate > ((FTDI_UART_FREQUENCY * 100) / 97))) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Baud Rates of 2000000 and 3000000 are special cases
- //
- if ((BaudRate >= FTDI_SPECIAL_CASE_300_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_300_MAX)) {
- *EncodedBaudRate = 0;
- return EFI_SUCCESS;
- }
- if ((BaudRate >= FTDI_SPECIAL_CASE_200_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_200_MAX)) {
- *EncodedBaudRate = 1;
- return EFI_SUCCESS;
- }
-
- //
- // Compute divisor
- //
- Divisor = (FTDI_UART_FREQUENCY << 4) / (UINT32)BaudRate;
-
- //
- // Round the last 4 bits to the nearest power of 2
- //
- Divisor = (Divisor & ~(0xF)) + (gRoundedPowersOf2[Divisor & 0xF]);
-
- //
- // Check to make sure computed divisor is within
- // the min and max that FTDI controller will accept
- //
- if (Divisor < FTDI_MIN_DIVISOR) {
- Divisor = FTDI_MIN_DIVISOR;
- } else if (Divisor > FTDI_MAX_DIVISOR) {
- Divisor = FTDI_MAX_DIVISOR;
- }
-
- //
- // Check to make sure the frequency that the FTDI chip will need to
- // generate to attain the requested Baud Rate is within 3% of the
- // 3MHz clock frequency that the FTDI chip runs at.
- //
- // (3MHz * 1600) / 103 = 46601941
- // (3MHz * 1600) / 97 = 49484536
- //
- AdjustedFrequency = (((UINT32)BaudRate) * Divisor);
- if ((AdjustedFrequency < FTDI_MIN_FREQUENCY) || (AdjustedFrequency > FTDI_MAX_FREQUENCY)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Encode the Divisor into the format FTDI expects
- //
- Result = (UINT16)(Divisor >> 4);
- if ((Divisor & 0x8) != 0) {
- Result |= 0x4000;
- } else if ((Divisor & 0x4) != 0) {
- Result |= 0x8000;
- } else if ((Divisor & 0x2) != 0) {
- Result |= 0xC000;
- }
-
- *EncodedBaudRate = Result;
- return EFI_SUCCESS;
-}
-
-/**
- Uses USB I/O to check whether the device is a USB Serial device.
-
- @param UsbIo[in] Pointer to a USB I/O protocol instance.
-
- @retval TRUE Device is a USB Serial device.
- @retval FALSE Device is a not USB Serial device.
-
-**/
-BOOLEAN
-IsUsbSerial (
- IN EFI_USB_IO_PROTOCOL *UsbIo
- )
-{
- EFI_STATUS Status;
- EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
- CHAR16 *StrMfg;
- BOOLEAN Found;
- UINT32 Index;
-
- //
- // Get the default device descriptor
- //
- Status = UsbIo->UsbGetDeviceDescriptor (
- UsbIo,
- &DeviceDescriptor
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
-
- Found = FALSE;
- Index = 0;
- while (gUSBDeviceList[Index].VendorId != 0 &&
- gUSBDeviceList[Index].DeviceId != 0 &&
- !Found ) {
- if (DeviceDescriptor.IdProduct == gUSBDeviceList[Index].DeviceId &&
- DeviceDescriptor.IdVendor == gUSBDeviceList[Index].VendorId ){
- //
- // Checks to see if a string descriptor can be pulled from the device in
- // the selected language. If not False is returned indicating that this
- // is not a Usb Serial Device that can be managegd by this driver
- //
- StrMfg = NULL;
- Status = UsbIo->UsbGetStringDescriptor (
- UsbIo,
- USB_US_LANG_ID, // LANGID selector, should make this
- // more robust to verify lang support
- // for device
- DeviceDescriptor.StrManufacturer,
- &StrMfg
- );
- if (StrMfg != NULL) {
- FreePool (StrMfg);
- }
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- return TRUE;
- }
- Index++;
- }
- return FALSE;
-}
-
-/**
- Internal function that sets the Data Bits, Stop Bits and Parity values on the
- Usb Serial Device with a single usb control transfer.
-
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param DataBits[in] The data bits value to be set on the Usb
- Serial Device
- @param Parity[in] The parity type that will be set on the Usb
- Serial Device
- @param StopBits[in] The stop bits type that will be set on the
- Usb Serial Device
- @param LastSettings[in] A pointer to the Usb Serial Device's
- PREVIOUS_ATTRIBUTES item
-
- @retval EFI_SUCCESS The data items were correctly set on the
- USB Serial Device
- @retval EFI_INVALID_PARAMETER An invalid data parameter or an invalid
- combination or parameters was used
- @retval EFI_DEVICE_ERROR The device is not functioning correctly and
- the data values were unable to be set
-
-**/
-EFI_STATUS
-EFIAPI
-SetDataInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN UINT8 DataBits,
- IN EFI_PARITY_TYPE Parity,
- IN EFI_STOP_BITS_TYPE StopBits,
- IN PREVIOUS_ATTRIBUTES *LastSettings
- )
-{
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
-
- //
- // Since data bits settings of 6,7,8 cannot be set with a stop bits setting of
- // 1.5 check to see if this happens when the values of last settings are used
- //
- if ((DataBits == 0) && (StopBits == OneFiveStopBits)) {
- if ((LastSettings->DataBits == 6) || (LastSettings->DataBits == 7) || (LastSettings->DataBits == 8)) {
- return EFI_INVALID_PARAMETER;
- }
- } else if ((StopBits == DefaultStopBits) && ((DataBits == 6) || (DataBits == 7) || (DataBits == 8))) {
- if (LastSettings->StopBits == OneFiveStopBits) {
- return EFI_INVALID_PARAMETER;
- }
- } else if ((DataBits == 0) && (StopBits == DefaultStopBits)) {
- if (LastSettings->StopBits == OneFiveStopBits) {
- if ((LastSettings->DataBits == 6) || (LastSettings->DataBits == 7) || (LastSettings->DataBits == 8)) {
- return EFI_INVALID_PARAMETER;
- }
- }
- }
-
- //
- // set the DevReq.Value for the usb control transfer to the correct value
- // based on the seleceted number of data bits if there is an invalid number of
- // data bits requested return EFI_INVALID_PARAMETER
- //
- if (((DataBits < 5 ) || (DataBits > 8)) && (DataBits != 0)) {
- return EFI_INVALID_PARAMETER;
- }
- if (DataBits == 0) {
- //
- // use the value of LastDataBits
- //
- DevReq.Value = SET_DATA_BITS (LastSettings->DataBits);
- } else {
- //
- // use the value of DataBits
- //
- DevReq.Value = SET_DATA_BITS (DataBits);
- }
-
- //
- // Set Parity
- //
- if (Parity == DefaultParity) {
- Parity = LastSettings->Parity;
- }
-
- if (Parity == NoParity) {
- DevReq.Value |= SET_PARITY_NONE;
- } else if (Parity == EvenParity) {
- DevReq.Value |= SET_PARITY_EVEN;
- } else if (Parity == OddParity){
- DevReq.Value |= SET_PARITY_ODD;
- } else if (Parity == MarkParity) {
- DevReq.Value |= SET_PARITY_MARK;
- } else if (Parity == SpaceParity) {
- DevReq.Value |= SET_PARITY_SPACE;
- }
-
- //
- // Set Stop Bits
- //
- if (StopBits == DefaultStopBits) {
- StopBits = LastSettings->StopBits;
- }
-
- if (StopBits == OneStopBit) {
- DevReq.Value |= SET_STOP_BITS_1;
- } else if (StopBits == OneFiveStopBits) {
- DevReq.Value |= SET_STOP_BITS_15;
- } else if (StopBits == TwoStopBits) {
- DevReq.Value |= SET_STOP_BITS_2;
- }
-
- //
- // set the rest of the DevReq parameters and perform the usb control transfer
- // to set the data bits on the device
- //
- DevReq.Request = FTDI_COMMAND_SET_DATA;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this request
-
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_SHORT_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- return Status;
-
-StatusError:
- if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
-}
-
-/**
- Internal function that sets the baudrate on the Usb Serial Device.
-
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param BaudRate[in] The baudrate value to be set on the device.
- If this value is 0 the value of LastBaudRate
- will be used instead
- @param LastBaudRate[in] The baud rate value that was previously set
- on the Usb Serial Device
-
- @retval EFI_SUCCESS The baudrate was set succesfully
- @retval EFI_INVALID_PARAMETER An invalid baudrate was used
- @retval EFI_DEVICE_ERROR The device is not functioning correctly and
- the baudrate was unable to be set
-
-**/
-EFI_STATUS
-EFIAPI
-SetBaudRateInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN UINT64 BaudRate,
- IN UINT64 LastBaudRate
- )
-{
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
- UINT16 EncodedBaudRate;
- EFI_TPL Tpl;
-
- Tpl = gBS->RaiseTPL(TPL_NOTIFY);
-
- //
- // set the value of DevReq.Value based on the value of BaudRate
- // if 0 is selected as baud rate use the value of LastBaudRate
- //
- if (BaudRate == 0) {
- Status = EncodeBaudRateForFtdi (LastBaudRate, &EncodedBaudRate);
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- //
- // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
- // succesfull
- //
- return Status;
- }
- DevReq.Value = EncodedBaudRate;
- } else {
- Status = EncodeBaudRateForFtdi (BaudRate, &EncodedBaudRate);
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- //
- // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
- // successfull
- //
- return Status;
- }
- DevReq.Value = EncodedBaudRate;
- }
-
- //
- // set the remaining parameters of DevReq and perform the usb control transfer
- // to set the device
- //
- DevReq.Request = FTDI_COMMAND_SET_BAUDRATE;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this request
-
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_SHORT_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- gBS->RestoreTPL (Tpl);
- return Status;
-
-StatusError:
- gBS->RestoreTPL (Tpl);
- if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
-}
-
-/**
- Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
- data bits, and stop bits on a serial device.
-
- @param UsbSerialDevice[in] Pointer to the current instance of the USB Serial
- Device.
- @param BaudRate[in] The requested baud rate. A BaudRate value of 0
- will use the device's default interface speed.
- @param ReveiveFifoDepth[in] The requested depth of the FIFO on the receive
- side of the serial interface. A ReceiveFifoDepth
- value of 0 will use the device's default FIFO
- depth.
- @param Timeout[in] The requested time out for a single character in
- microseconds.This timeout applies to both the
- transmit and receive side of the interface.A
- Timeout value of 0 will use the device's default
- time out value.
- @param Parity[in] The type of parity to use on this serial device.
- A Parity value of DefaultParity will use the
- device's default parity value.
- @param DataBits[in] The number of data bits to use on the serial
- device. A DataBits value of 0 will use the
- device's default data bit setting.
- @param StopBits[in] The number of stop bits to use on this serial
- device. A StopBits value of DefaultStopBits will
- use the device's default number of stop bits.
-
- @retval EFI_SUCCESS The attributes were set
- @retval EFI_DEVICE_ERROR The attributes were not able to be set
-
-**/
-EFI_STATUS
-EFIAPI
-SetAttributesInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- IN UINT64 BaudRate,
- IN UINT32 ReceiveFifoDepth,
- IN UINT32 Timeout,
- IN EFI_PARITY_TYPE Parity,
- IN UINT8 DataBits,
- IN EFI_STOP_BITS_TYPE StopBits
- )
-{
- EFI_STATUS Status;
- EFI_TPL Tpl;
- UART_DEVICE_PATH *Uart;
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
-
- Status = EFI_UNSUPPORTED;
- Tpl = gBS->RaiseTPL(TPL_NOTIFY);
- Uart = NULL;
-
- //
- // check for invalid combinations of parameters
- //
- if (((DataBits >= 6) && (DataBits <= 8)) && (StopBits == OneFiveStopBits)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // set data bits, parity and stop bits
- //
- Status = SetDataInternal (
- UsbSerialDevice->UsbIo,
- DataBits,
- Parity,
- StopBits,
- &(UsbSerialDevice->LastSettings)
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- //
- // set baudrate
- //
- Status = SetBaudRateInternal (
- UsbSerialDevice->UsbIo,
- BaudRate,
- UsbSerialDevice->LastSettings.BaudRate
- );
- if (EFI_ERROR (Status)){
- goto StatusError;
- }
-
- //
- // update the values of UsbSerialDevice->LastSettings and UsbSerialDevice->SerialIo.Mode
- //
- if (BaudRate == 0) {
- UsbSerialDevice->LastSettings.BaudRate = UsbSerialDevice->LastSettings.BaudRate;
- UsbSerialDevice->SerialIo.Mode->BaudRate = UsbSerialDevice->LastSettings.BaudRate;
- } else {
- UsbSerialDevice->LastSettings.BaudRate = BaudRate;
- UsbSerialDevice->SerialIo.Mode->BaudRate = BaudRate;
- }
-
- UsbSerialDevice->LastSettings.Timeout = FTDI_TIMEOUT;
- UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;
-
- if (Parity == DefaultParity) {
- UsbSerialDevice->LastSettings.Parity = UsbSerialDevice->LastSettings.Parity;
- UsbSerialDevice->SerialIo.Mode->Parity = UsbSerialDevice->LastSettings.Parity;
- } else {
- UsbSerialDevice->LastSettings.Parity = Parity;
- UsbSerialDevice->SerialIo.Mode->Parity = Parity;
- }
- if (DataBits == 0) {
- UsbSerialDevice->LastSettings.DataBits = UsbSerialDevice->LastSettings.DataBits;
- UsbSerialDevice->SerialIo.Mode->DataBits = UsbSerialDevice->LastSettings.DataBits;
- } else {
- UsbSerialDevice->LastSettings.DataBits = DataBits;
- UsbSerialDevice->SerialIo.Mode->DataBits = DataBits;
- }
- if (StopBits == DefaultStopBits) {
- UsbSerialDevice->LastSettings.StopBits = UsbSerialDevice->LastSettings.StopBits;
- UsbSerialDevice->SerialIo.Mode->StopBits = UsbSerialDevice->LastSettings.StopBits;
- } else {
- UsbSerialDevice->LastSettings.StopBits = StopBits;
- UsbSerialDevice->SerialIo.Mode->StopBits = StopBits;
- }
-
- //
- // See if the device path node has changed
- //
- if (UsbSerialDevice->UartDevicePath.BaudRate == BaudRate &&
- UsbSerialDevice->UartDevicePath.DataBits == DataBits &&
- UsbSerialDevice->UartDevicePath.StopBits == StopBits &&
- UsbSerialDevice->UartDevicePath.Parity == Parity
- ) {
- gBS->RestoreTPL (Tpl);
- return EFI_SUCCESS;
- }
-
- //
- // Update the device path
- //
- UsbSerialDevice->UartDevicePath.BaudRate = BaudRate;
- UsbSerialDevice->UartDevicePath.DataBits = DataBits;
- UsbSerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
- UsbSerialDevice->UartDevicePath.Parity = (UINT8) Parity;
-
- Status = EFI_SUCCESS;
- if (UsbSerialDevice->ControllerHandle != NULL) {
- RemainingDevicePath = UsbSerialDevice->DevicePath;
- while (!IsDevicePathEnd (RemainingDevicePath)) {
- Uart = (UART_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (Uart->Header.Type == MESSAGING_DEVICE_PATH &&
- Uart->Header.SubType == MSG_UART_DP &&
- sizeof (UART_DEVICE_PATH) == DevicePathNodeLength ((EFI_DEVICE_PATH *) Uart)) {
- Uart->BaudRate = BaudRate;
- Uart->DataBits = DataBits;
- Uart->StopBits = (UINT8)StopBits;
- Uart->Parity = (UINT8) Parity;
- break;
- }
- RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
- }
- }
-
- gBS->RestoreTPL (Tpl);
- return Status;
-
-StatusError:
- gBS->RestoreTPL (Tpl);
- if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
-}
-
-/**
- Internal function that performs a Usb Control Transfer to set the flow control
- on the Usb Serial Device.
-
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param FlowControlEnable[in] Data on the Enable/Disable status of Flow
- Control on the Usb Serial Device
-
- @retval EFI_SUCCESS The flow control was set on the Usb Serial
- device
- @retval EFI_INVALID_PARAMETER An invalid flow control value was used
- @retval EFI_EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
-
-**/
-EFI_STATUS
-EFIAPI
-SetFlowControlInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN BOOLEAN FlowControlEnable
- )
-{
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
-
- //
- // set DevReq.Value based on the value of FlowControlEnable
- //
- if (!FlowControlEnable) {
- DevReq.Value = NO_FLOW_CTRL;
- }
- if (FlowControlEnable) {
- DevReq.Value = XON_XOFF_CTRL;
- }
- //
- // set the remaining DevReq parameters and perform the usb control transfer to
- // set the flow control on the device
- //
- DevReq.Request = FTDI_COMMAND_SET_FLOW_CTRL;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that this transfer has no data phase
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
-
- return Status;
-
-StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
-}
-
-/**
- Internal function that performs a Usb Control Transfer to set the Dtr value on
- the Usb Serial Device.
-
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param DtrEnable[in] Data on the Enable/Disable status of the
- Dtr for the Usb Serial Device
-
- @retval EFI_SUCCESS The Dtr value was set on the Usb Serial
- Device
- @retval EFI_INVALID_PARAMETER An invalid Dtr value was used
- @retval EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
-
-**/
-EFI_STATUS
-EFIAPI
-SetDtrInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN BOOLEAN DtrEnable
- )
-{
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
-
- //
- // set the value of DevReq.Value based on the value of DtrEnable
- //
- if (!DtrEnable) {
- DevReq.Value = SET_DTR_LOW;
- }
- if (DtrEnable) {
- DevReq.Value = SET_DTR_HIGH;
- }
- //
- // set the remaining attributes of DevReq and perform the usb control transfer
- // to set the device
- //
- DevReq.Request = FTDI_COMMAND_MODEM_CTRL;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this transfer
-
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- return Status;
-
-StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
-}
-
-/**
- Internal function that performs a Usb Control Transfer to set the Dtr value on
- the Usb Serial Device.
-
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param RtsEnable[in] Data on the Enable/Disable status of the
- Rts for the Usb Serial Device
-
- @retval EFI_SUCCESS The Rts value was set on the Usb Serial
- Device
- @retval EFI_INVALID_PARAMETER An invalid Rts value was used
- @retval EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
-
-**/
-EFI_STATUS
-EFIAPI
-SetRtsInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN BOOLEAN RtsEnable
- )
-{
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
-
- //
- // set DevReq.Value based on the value of RtsEnable
- //
- if (!RtsEnable) {
- DevReq.Value = SET_RTS_LOW;
- }
- if (RtsEnable) {
- DevReq.Value = SET_RTS_HIGH;
- }
-
- //
- // set the remaining parameters of DevReq and perform the usb control transfer
- // to set the values on the device
- //
- DevReq.Request = FTDI_COMMAND_MODEM_CTRL;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this request
-
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
-
- return Status;
-
-StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
-}
-
-/**
- Internal function that checks for valid control values and sets the control
- bits on the Usb Serial Device.
-
- @param UsbSerialDevice[in] Handle to the Usb Serial Device whose
- control bits are being set
- @param Control[in] The control value passed to the function
- that contains the values of the control
- bits that are being set
-
- @retval EFI_SUCCESS The control bits were set on the Usb Serial
- Device
- @retval EFI_INVALID_PARAMETER An invalid control value was encountered
- @retval EFI_EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
-
-**/
-EFI_STATUS
-EFIAPI
-SetControlBitsInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- IN CONTROL_BITS *Control
- )
-{
- EFI_STATUS Status;
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
-
- //
- // check for invalid control parameters hardware and software loopback enabled
- // must always be set to FALSE
- //
- Control->HardwareLoopBack = FALSE;
- Control->SoftwareLoopBack = FALSE;
-
- //
- // set hardware flow control
- //
- Status = SetFlowControlInternal (
- UsbSerialDevice->UsbIo,
- Control->HardwareFlowControl
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
-
- //
- // set Dtr state
- //
- Status = SetDtrInternal (UsbSerialDevice->UsbIo, Control->DtrState);
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
-
- //
- // set Rts state
- //
- Status = SetRtsInternal (UsbSerialDevice->UsbIo, Control->RtsState);
- if (EFI_ERROR (Status)){
- goto StatusError;
- }
-
- //
- // update the remaining control values for UsbSerialDevice->ControlValues
- //
- UsbSerialDevice->ControlValues.DtrState = Control->DtrState;
- UsbSerialDevice->ControlValues.RtsState = Control->RtsState;
- UsbSerialDevice->ControlValues.HardwareFlowControl = Control->HardwareFlowControl;
- UsbSerialDevice->ControlValues.HardwareLoopBack = FALSE;
- UsbSerialDevice->ControlValues.SoftwareLoopBack = FALSE;
-
- Status = EFI_SUCCESS;
- //
- // Update the device path to have the correct flow control values
- //
- if (UsbSerialDevice->ControllerHandle != NULL) {
- RemainingDevicePath = UsbSerialDevice->DevicePath;
- while (!IsDevicePathEnd (RemainingDevicePath)) {
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (FlowControl->Header.Type == MESSAGING_DEVICE_PATH &&
- FlowControl->Header.SubType == MSG_VENDOR_DP &&
- sizeof (UART_FLOW_CONTROL_DEVICE_PATH) == DevicePathNodeLength ((EFI_DEVICE_PATH *) FlowControl)){
- if (UsbSerialDevice->ControlValues.HardwareFlowControl == TRUE) {
- FlowControl->FlowControlMap = UART_FLOW_CONTROL_HARDWARE;
- } else if (UsbSerialDevice->ControlValues.HardwareFlowControl == FALSE) {
- FlowControl->FlowControlMap = 0;
- }
- break;
- }
- RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
- }
- }
-
- return Status;
-
-StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
-}
-
-/**
- Internal function that calculates the Control value used by GetControlBits()
- based on the status and control values of the Usb Serial Device.
-
- @param UsbSerialDevice[in] Handle to the Usb Serial Devie whose status
- and control values are being used to set
- Control
- @param Control[out] On output the formated value of Control
- that has been calculated based on the
- control and status values of the Usb Serial
- Device
-
- @retval EFI_SUCCESS The value of Control was successfully
- calculated
-
-**/
-EFI_STATUS
-EFIAPI
-GetControlBitsInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- OUT UINT32 *Control
- )
-{
- *Control = 0;
-
- //
- // Check the values of UsbSerialDevice->Status Values and modify control
- // accordingly these values correspond to the modem status register
- //
- if (UsbSerialDevice->StatusValues.CtsState) {
- *Control |= EFI_SERIAL_CLEAR_TO_SEND;
- }
- if (UsbSerialDevice->StatusValues.DsrState) {
- *Control |= EFI_SERIAL_DATA_SET_READY;
- }
- if (UsbSerialDevice->StatusValues.RiState) {
- *Control |= EFI_SERIAL_RING_INDICATE;
- }
- if (UsbSerialDevice->StatusValues.SdState) {
- *Control |= EFI_SERIAL_CARRIER_DETECT;
- }
-
- //
- // check the values of UsbSerialDevice->ControlValues and modify control
- // accordingly these values correspond to the values of the Modem Control
- // Register
- //
- if (UsbSerialDevice->ControlValues.DtrState) {
- *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
- }
- if (UsbSerialDevice->ControlValues.RtsState) {
- *Control |= EFI_SERIAL_REQUEST_TO_SEND;
- }
- if (UsbSerialDevice->ControlValues.HardwareLoopBack) {
- *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
- }
- if (UsbSerialDevice->ControlValues.HardwareFlowControl) {
- *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
- //
- // check if the buffer is empty since only one is being used if it is empty
- // set both the receive and transmit buffers to empty
- //
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
- *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
- }
- //
- // check for software loopback enable in UsbSerialDevice->ControlValues
- //
- if (UsbSerialDevice->ControlValues.SoftwareLoopBack) {
- *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Resets the USB Serial Device
-
- This function is the internal method for resetting the device and is called by
- SerialReset()
-
- @param UsbSerialDevice[in] A pointer to the USB Serial device
-
- @retval EFI_SUCCESS The device was reset
- @retval EFI_DEVICE_ERROR The device could not be reset
-
-**/
-EFI_STATUS
-EFIAPI
-ResetInternal (
- IN USB_SER_DEV *UsbSerialDevice
- )
-{
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT8 ConfigurationValue;
- UINT32 ReturnValue;
-
- DevReq.Request = FTDI_COMMAND_RESET_PORT;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Value = RESET_PORT_PURGE_RX;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; //indicates that there is not data phase in this request
-
- Status = UsbSerialDevice->UsbIo->UsbControlTransfer (
- UsbSerialDevice->UsbIo,
- &DevReq,
- EfiUsbDataIn,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- DevReq.Request = FTDI_COMMAND_RESET_PORT;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Value = RESET_PORT_PURGE_TX;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; //indicates that there is no data phase in this request
-
- Status = UsbSerialDevice->UsbIo->UsbControlTransfer (
- UsbSerialDevice->UsbIo,
- &DevReq,
- EfiUsbDataIn,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- return Status;
-}
-
-/**
- Entrypoint of USB Serial Driver.
-
- This function is the entrypoint of USB Serial Driver. It installs
- Driver Binding Protocols together with Component Name Protocols.
-
- @param ImageHandle[in] The firmware allocated handle for the EFI image.
- @param SystemTable[in] A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The entry point is executed successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-FtdiUsbSerialEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
-
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gUsbSerialDriverBinding,
- ImageHandle,
- &gUsbSerialComponentName,
- &gUsbSerialComponentName2
- );
- ASSERT_EFI_ERROR (Status);
- return EFI_SUCCESS;
-}
-
-/**
- Unload function for the Usb Serial Driver.
-
- @param ImageHandle[in] The allocated handle for the EFI image
-
- @retval EFI_SUCCESS The driver was unloaded successfully
-**/
-EFI_STATUS
-EFIAPI
-FtdiUsbSerialUnload (
- IN EFI_HANDLE ImageHandle
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
-
- //
- // Retrieve all handles in the handle database
- //
- Status = gBS->LocateHandleBuffer (
- AllHandles,
- NULL,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Disconnect the driver from the handles in the handle database
- //
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->DisconnectController (
- HandleBuffer[Index],
- gImageHandle,
- NULL
- );
- }
-
- //
- // Free the handle array
- //
- FreePool (HandleBuffer);
-
- //
- // Uninstall protocols installed by the driver in its entrypoint
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ImageHandle,
- &gEfiDriverBindingProtocolGuid,
- &gUsbSerialDriverBinding,
- &gEfiComponentNameProtocolGuid,
- &gUsbSerialComponentName,
- &gEfiComponentName2ProtocolGuid,
- &gUsbSerialComponentName2,
- NULL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Check whether USB Serial driver supports this device.
-
- @param This[in] The USB Serial driver binding protocol.
- @param Controller[in] The controller handle to check.
- @param RemainingDevicePath[in] The remaining device path.
-
- @retval EFI_SUCCESS The driver supports this controller.
- @retval other This device isn't supported.
-
-**/
-EFI_STATUS
-EFIAPI
-UsbSerialDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
-{
- EFI_STATUS Status;
- EFI_USB_IO_PROTOCOL *UsbIo;
- UART_DEVICE_PATH *UartNode;
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
- UINTN Index;
- UINTN EntryCount;
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
- BOOLEAN HasFlowControl;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
-
- if (RemainingDevicePath != NULL) {
- if (!IsDevicePathEnd (RemainingDevicePath)) {
- Status = EFI_UNSUPPORTED;
- UartNode = (UART_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
- UartNode->Header.SubType != MSG_UART_DP ||
- sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH *) UartNode)) {
- goto Error;
- }
- FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);
- if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
- goto Error;
- }
- }
- }
-
- //
- // Check if USB I/O Protocol is attached on the controller handle.
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (Status == EFI_ALREADY_STARTED) {
- if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
- return EFI_SUCCESS;
- }
- Status = gBS->OpenProtocolInformation (
- Controller,
- &gEfiUsbIoProtocolGuid,
- &OpenInfoBuffer,
- &EntryCount
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- for (Index = 0; Index < EntryCount; Index++) {
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- Status = gBS->OpenProtocol (
- OpenInfoBuffer[Index].ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &DevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- HasFlowControl = ContainsFlowControl (RemainingDevicePath);
- if (HasFlowControl ^ ContainsFlowControl (DevicePath)) {
- Status = EFI_UNSUPPORTED;
- }
- }
- break;
- }
- }
- FreePool (OpenInfoBuffer);
- return Status;
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
-
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ParentDevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (Status == EFI_ALREADY_STARTED) {
- return EFI_SUCCESS;
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Use the USB I/O Protocol interface to check whether Controller is
- // a USB Serial device that can be managed by this driver.
- //
- Status = EFI_SUCCESS;
-
- if (!IsUsbSerial (UsbIo)) {
- Status = EFI_UNSUPPORTED;
- goto Error;
- }
-
-Error:
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- return Status;
-}
-
-/**
- Starts the USB Serial device with this driver.
-
- This function produces initializes the USB Serial device and
- produces the Serial IO Protocol.
-
- @param This[in] The USB Serial driver binding instance.
- @param Controller[in] Handle of device to bind driver to.
- @param RemainingDevicePath[in] Optional parameter use to pick a specific
- child device to start.
-
- @retval EFI_SUCCESS The controller is controlled by the usb USB
- Serial driver.
- @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
- @retval Other This controller cannot be started.
-
-**/
-EFI_STATUS
-EFIAPI
-UsbSerialDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
-{
- EFI_STATUS Status;
- EFI_USB_IO_PROTOCOL *UsbIo;
- USB_SER_DEV *UsbSerialDevice;
- UINT8 EndpointNumber;
- EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
- UINT8 Index;
- BOOLEAN FoundIn;
- BOOLEAN FoundOut;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
- UINTN EntryCount;
- EFI_SERIAL_IO_PROTOCOL *SerialIo;
- UART_DEVICE_PATH *Uart;
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
- UINT32 Control;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
-
- UsbSerialDevice = AllocateZeroPool (sizeof (USB_SER_DEV));
- ASSERT (UsbSerialDevice != NULL);
-
- //
- // Get the Parent Device path
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ParentDevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
- goto ErrorExit1;
- }
-
- //
- // Open USB I/O Protocol
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
- goto ErrorExit1;
- }
-
- if (Status == EFI_ALREADY_STARTED) {
- if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
- FreePool (UsbSerialDevice);
- return EFI_SUCCESS;
- }
-
- //
- // Check to see if a child handle exists
- //
- Status = gBS->OpenProtocolInformation (
- Controller,
- &gEfiSerialIoProtocolGuid,
- &OpenInfoBuffer,
- &EntryCount
- );
- if (EFI_ERROR (Status)) {
- goto ErrorExit1;
- }
-
- Status = EFI_ALREADY_STARTED;
- for (Index = 0; Index < EntryCount; Index++) {
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- Status = gBS->OpenProtocol (
- OpenInfoBuffer[Index].ControllerHandle,
- &gEfiSerialIoProtocolGuid,
- (VOID **) &SerialIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- }
- if (!EFI_ERROR (Status)) {
- Uart = (UART_DEVICE_PATH *) RemainingDevicePath;
- Status = SerialIo->SetAttributes (
- SerialIo,
- Uart->BaudRate,
- SerialIo->Mode->ReceiveFifoDepth,
- SerialIo->Mode->Timeout,
- (EFI_PARITY_TYPE) Uart->Parity,
- Uart->DataBits,
- (EFI_STOP_BITS_TYPE) Uart->StopBits
- );
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
- if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {
- Status = SerialIo->GetControl (
- SerialIo,
- &Control
- );
- if (!EFI_ERROR (Status)) {
- if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) {
- Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- } else {
- Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
- //
- // Clear bits that are not allowed to be passed to SetControl
- //
- Control &= (EFI_SERIAL_REQUEST_TO_SEND |
- EFI_SERIAL_DATA_TERMINAL_READY |
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);
- Status = SerialIo->SetControl (SerialIo, Control);
- }
- }
- }
- break;
- }
- }
- FreePool (OpenInfoBuffer);
- return Status;
- }
-
- if (RemainingDevicePath != NULL) {
- if (IsDevicePathEnd (RemainingDevicePath)) {
- return EFI_SUCCESS;
- }
- }
-
- UsbSerialDevice->UsbIo = UsbIo;
-
- //
- // Get interface & endpoint descriptor
- //
- UsbIo->UsbGetInterfaceDescriptor (
- UsbIo,
- &UsbSerialDevice->InterfaceDescriptor
- );
-
- EndpointNumber = UsbSerialDevice->InterfaceDescriptor.NumEndpoints;
-
- //
- // Traverse endpoints to find the IN and OUT endpoints that will send and
- // receive data.
- //
- FoundIn = FALSE;
- FoundOut = FALSE;
- for (Index = 0; Index < EndpointNumber; Index++) {
-
- Status = UsbIo->UsbGetEndpointDescriptor (
- UsbIo,
- Index,
- &EndpointDescriptor
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_OUT) {
- //
- // Set the Out endpoint device
- //
- CopyMem (
- &UsbSerialDevice->OutEndpointDescriptor,
- &EndpointDescriptor,
- sizeof(EndpointDescriptor)
- );
- FoundOut = TRUE;
- }
-
- if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_IN) {
- //
- // Set the In endpoint device
- //
- CopyMem (
- &UsbSerialDevice->InEndpointDescriptor,
- &EndpointDescriptor,
- sizeof(EndpointDescriptor)
- );
- FoundIn = TRUE;
- }
- }
-
- if (!FoundIn || !FoundOut) {
- //
- // No interrupt endpoint found, then return unsupported.
- //
- Status = EFI_UNSUPPORTED;
- goto ErrorExit;
- }
- //
- // set the initial values of UsbSerialDevice->LastSettings to the default
- // values
- //
- UsbSerialDevice->LastSettings.BaudRate = 115200;
- UsbSerialDevice->LastSettings.DataBits = 8;
- UsbSerialDevice->LastSettings.Parity = NoParity;
- UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;
- UsbSerialDevice->LastSettings.StopBits = OneStopBit;
- UsbSerialDevice->LastSettings.Timeout = FTDI_TIMEOUT;
-
- //
- // set the initial values of UsbSerialDevice->ControlValues
- //
- UsbSerialDevice->ControlValues.DtrState = FALSE;
- UsbSerialDevice->ControlValues.RtsState = FALSE;
- UsbSerialDevice->ControlValues.HardwareFlowControl = FALSE;
- UsbSerialDevice->ControlValues.HardwareLoopBack = FALSE;
- UsbSerialDevice->ControlValues.SoftwareLoopBack = FALSE;
-
- //
- // set the values of UsbSerialDevice->UartDevicePath
- //
- UsbSerialDevice->UartDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
- UsbSerialDevice->UartDevicePath.Header.SubType = MSG_UART_DP;
- UsbSerialDevice->UartDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_DEVICE_PATH));
- UsbSerialDevice->UartDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8);
-
- //
- // set the values of UsbSerialDevice->FlowControlDevicePath
- UsbSerialDevice->FlowControlDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
- UsbSerialDevice->FlowControlDevicePath.Header.SubType = MSG_VENDOR_DP;
- UsbSerialDevice->FlowControlDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_FLOW_CONTROL_DEVICE_PATH));
- UsbSerialDevice->FlowControlDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_FLOW_CONTROL_DEVICE_PATH)) >> 8);
- UsbSerialDevice->FlowControlDevicePath.FlowControlMap = 0;
-
- Status = SetAttributesInternal (
- UsbSerialDevice,
- UsbSerialDevice->LastSettings.BaudRate,
- UsbSerialDevice->LastSettings.ReceiveFifoDepth,
- UsbSerialDevice->LastSettings.Timeout,
- UsbSerialDevice->LastSettings.Parity,
- UsbSerialDevice->LastSettings.DataBits,
- UsbSerialDevice->LastSettings.StopBits
- );
-
- ASSERT_EFI_ERROR (Status);
-
- Status = SetControlBitsInternal (
- UsbSerialDevice,
- &(UsbSerialDevice->ControlValues)
- );
-
- ASSERT_EFI_ERROR (Status);
-
- //
- // Publish Serial GUID and protocol
- //
-
- UsbSerialDevice->Signature = USB_SER_DEV_SIGNATURE;
- UsbSerialDevice->SerialIo.Reset = SerialReset;
- UsbSerialDevice->SerialIo.SetControl = SetControlBits;
- UsbSerialDevice->SerialIo.SetAttributes = SetAttributes;
- UsbSerialDevice->SerialIo.GetControl = GetControlBits;
- UsbSerialDevice->SerialIo.Read = ReadSerialIo;
- UsbSerialDevice->SerialIo.Write = WriteSerialIo;
-
- //
- // Set the static Serial IO modes that will display when running
- // "sermode" within the UEFI shell.
- //
-
- UsbSerialDevice->SerialIo.Mode->Timeout = 0;
- UsbSerialDevice->SerialIo.Mode->BaudRate = 115200;
- UsbSerialDevice->SerialIo.Mode->DataBits = 8;
- UsbSerialDevice->SerialIo.Mode->Parity = 1;
- UsbSerialDevice->SerialIo.Mode->StopBits = 1;
-
- UsbSerialDevice->ParentDevicePath = ParentDevicePath;
- UsbSerialDevice->ControllerHandle = NULL;
- FlowControl = NULL;
-
- //
- // Allocate space for the receive buffer
- //
- UsbSerialDevice->DataBuffer = AllocateZeroPool (SW_FIFO_DEPTH);
-
- //
- // Initialize data buffer pointers.
- // Head==Tail = true means buffer is empty.
- //
- UsbSerialDevice->DataBufferHead = 0;
- UsbSerialDevice->DataBufferTail = 0;
-
- UsbSerialDevice->ControllerNameTable = NULL;
- AddUnicodeString2 (
- "eng",
- gUsbSerialComponentName.SupportedLanguages,
- &UsbSerialDevice->ControllerNameTable,
- L"FTDI USB Serial Adapter",
- TRUE
- );
- AddUnicodeString2 (
- "en",
- gUsbSerialComponentName2.SupportedLanguages,
- &UsbSerialDevice->ControllerNameTable,
- L"FTDI USB Serial Adapter",
- FALSE
- );
-
- Status = SetInitialStatus (UsbSerialDevice);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Create a polling loop to check for input
- //
-
- gBS->CreateEvent (
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- UsbSerialDriverCheckInput,
- UsbSerialDevice,
- &(UsbSerialDevice->PollingLoop)
- );
- //
- // add code to set trigger time based on baud rate
- // setting to 0.5s for now
- //
- gBS->SetTimer (
- UsbSerialDevice->PollingLoop,
- TimerPeriodic,
- EFI_TIMER_PERIOD_MILLISECONDS (500)
- );
-
- //
- // Check if the remaining device path is null. If it is not null change the settings
- // of the device to match those on the device path
- //
- if (RemainingDevicePath != NULL) {
- CopyMem (
- &UsbSerialDevice->UartDevicePath,
- RemainingDevicePath,
- sizeof (UART_DEVICE_PATH)
- );
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (IsUartFlowControlNode (FlowControl)) {
- UsbSerialDevice->FlowControlDevicePath.FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap);
- } else {
- FlowControl = NULL;
- }
- }
-
- //
- // Build the device path by appending the UART node to the parent device path
- //
- UsbSerialDevice->DevicePath = AppendDevicePathNode (
- ParentDevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->UartDevicePath
- );
- //
- // Continue building the device path by appending the flow control node
- //
- TempDevicePath = UsbSerialDevice->DevicePath;
- UsbSerialDevice->DevicePath = AppendDevicePathNode (
- TempDevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->FlowControlDevicePath
- );
- FreePool (TempDevicePath);
-
- if (UsbSerialDevice->DevicePath == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ErrorExit;
- }
-
- //
- // Install protocol interfaces for the device
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &UsbSerialDevice->ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- UsbSerialDevice->DevicePath,
- &gEfiSerialIoProtocolGuid,
- &UsbSerialDevice->SerialIo,
- NULL
- );
- if (EFI_ERROR (Status)){
- goto ErrorExit;
- }
-
- //
- // Open for child device
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- UsbSerialDevice->ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
-
- UsbSerialDevice->Shutdown = FALSE;
-
- return EFI_SUCCESS;
-
-ErrorExit:
- //
- // Error handler
- //
-
- Status = gBS->UninstallMultipleProtocolInterfaces (
- Controller,
- &gEfiSerialIoProtocolGuid,
- &UsbSerialDevice->SerialIo,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ErrorExit1;
- }
-
- FreePool (UsbSerialDevice->DataBuffer);
- FreePool (UsbSerialDevice);
-
- UsbSerialDevice = NULL;
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
-
-ErrorExit1:
- return Status;
-}
-
-/**
- Stop the USB Serial device handled by this driver.
-
- @param This[in] The USB Serial driver binding protocol.
- @param Controller[in] The controller to release.
- @param NumberOfChildren[in] The number of handles in ChildHandleBuffer.
- @param ChildHandleBuffer[in] The array of child handle.
-
- @retval EFI_SUCCESS The device was stopped.
- @retval EFI_UNSUPPORTED Serial IO Protocol is not installed on
- Controller.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a
- device error.
- @retval Others Fail to uninstall protocols attached on the
- device.
-
-**/
-EFI_STATUS
-EFIAPI
-UsbSerialDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
-{
- EFI_STATUS Status;
- EFI_SERIAL_IO_PROTOCOL *SerialIo;
- EFI_USB_IO_PROTOCOL *UsbIo;
- USB_SER_DEV *UsbSerialDevice;
- UINTN Index;
- BOOLEAN AllChildrenStopped;
-
- Status = EFI_SUCCESS;
- UsbSerialDevice = NULL;
-
- if (NumberOfChildren == 0) {
- //
- // Close the driver
- //
- Status = gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- Status = gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- return Status;
- }
-
- AllChildrenStopped = TRUE;
-
- for (Index = 0; Index < NumberOfChildren ;Index++) {
- Status = gBS->OpenProtocol (
- ChildHandleBuffer[Index],
- &gEfiSerialIoProtocolGuid,
- (VOID **) &SerialIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (Status == EFI_SUCCESS) {//!EFI_ERROR (Status)) {
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (SerialIo);
- Status = gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- ChildHandleBuffer[Index]
- );
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ChildHandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- UsbSerialDevice->DevicePath,
- &gEfiSerialIoProtocolGuid,
- &UsbSerialDevice->SerialIo,
- NULL
- );
-
- if (EFI_ERROR (Status)) {
- gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- ChildHandleBuffer[Index],
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- } else {
- if (UsbSerialDevice->DevicePath != NULL) {
- gBS->FreePool (UsbSerialDevice->DevicePath);
- }
- gBS->SetTimer (
- UsbSerialDevice->PollingLoop,
- TimerCancel,
- 0
- );
- gBS->CloseEvent (UsbSerialDevice->PollingLoop);
- UsbSerialDevice->Shutdown = TRUE;
- FreeUnicodeStringTable (UsbSerialDevice->ControllerNameTable);
- FreePool (UsbSerialDevice->DataBuffer);
- FreePool (UsbSerialDevice);
- }
- }
- if (EFI_ERROR (Status)) {
- AllChildrenStopped = FALSE;
- }
- }
-
- if (!AllChildrenStopped) {
- return EFI_DEVICE_ERROR;
- }
- return EFI_SUCCESS;
-}
-
-//
-// Serial IO Member Functions
-//
-
-/**
- Reset the serial device.
-
- @param This[in] Protocol instance pointer.
-
- @retval EFI_SUCCESS The device was reset.
- @retval EFI_DEVICE_ERROR The serial device could not be reset.
-
-**/
-EFI_STATUS
-EFIAPI
-SerialReset (
- IN EFI_SERIAL_IO_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
-
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
- Status = ResetInternal (UsbSerialDevice);
- if (EFI_ERROR (Status)){
- return EFI_DEVICE_ERROR;
- }
- return Status;
-}
-
-/**
- Set the control bits on a serial device.
-
- @param This[in] Protocol instance pointer.
- @param Control[in] Set the bits of Control that are settable.
-
- @retval EFI_SUCCESS The new control bits were set on the serial device.
- @retval EFI_UNSUPPORTED The serial device does not support this operation.
- @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
-
-**/
-EFI_STATUS
-EFIAPI
-SetControlBits (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN UINT32 Control
- )
-{
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
- CONTROL_BITS ControlBits;
-
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
-
- //
- // check for invalid control parameters
- //
- if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND |
- EFI_SERIAL_DATA_TERMINAL_READY |
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0 ) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // check the control parameters and set the correct setting for
- // the paramerts of ControlBits
- // both loopback enables are always set to FALSE
- //
- ControlBits.HardwareLoopBack = FALSE;
- ControlBits.SoftwareLoopBack = FALSE;
- //
- // check for hardware flow control
- //
- if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
- ControlBits.HardwareFlowControl = TRUE;
- } else {
- ControlBits.HardwareFlowControl = FALSE;
- }
- //
- // check for DTR enabled
- //
- if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
- ControlBits.DtrState = TRUE;
- } else {
- ControlBits.DtrState = FALSE;
- }
- //
- // check for RTS enabled
- //
- if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
- ControlBits.RtsState = TRUE;
- } else {
- ControlBits.RtsState = FALSE;
- }
-
- //
- // set the control values with a call to SetControlBitsInternal()
- //
- Status = SetControlBitsInternal (UsbSerialDevice, &ControlBits);
-
- return Status;
-}
-
-/**
- calls SetAttributesInternal() to set the baud rate, receive FIFO depth,
- transmit/receive time out, parity, data buts, and stop bits on a serial
- device.
-
- @param This[in] Protocol instance pointer.
- @param BaudRate[in] The requested baud rate. A BaudRate value of 0
- will use the device's default interface speed.
- @param ReveiveFifoDepth[in] The requested depth of the FIFO on the receive
- side of the serial interface. A ReceiveFifoDepth
- value of 0 will use the device's default FIFO
- depth.
- @param Timeout[in] The requested time out for a single character in
- microseconds.This timeout applies to both the
- transmit and receive side of the interface. A
- Timeout value of 0 will use the device's default
- time out value.
- @param Parity[in] The type of parity to use on this serial device.
- A Parity value of DefaultParity will use the
- device's default parity value.
- @param DataBits[in] The number of data bits to use on the serial
- device. A DataBit vaule of 0 will use the
- device's default data bit setting.
- @param StopBits[in] The number of stop bits to use on this serial
- device. A StopBits value of DefaultStopBits will
- use the device's default number of stop bits.
-
- @retval EFI_SUCCESS The attributes were set
- @retval EFI_DEVICE_ERROR The attributes were not able to be
-
-**/
-EFI_STATUS
-EFIAPI
-SetAttributes (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN UINT64 BaudRate,
- IN UINT32 ReceiveFifoDepth,
- IN UINT32 Timeout,
- IN EFI_PARITY_TYPE Parity,
- IN UINT8 DataBits,
- IN EFI_STOP_BITS_TYPE StopBits
- )
-{
-
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
-
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
-
- Status = SetAttributesInternal (
- UsbSerialDevice,
- BaudRate,
- ReceiveFifoDepth,
- Timeout,
- Parity,
- DataBits,
- StopBits
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- return Status;
-}
-
-
-/**
- Retrieves the status of the control bits on a serial device.
-
- @param This[in] Protocol instance pointer.
- @param Control[out] A pointer to return the current Control signals
- from the serial device.
-
- @retval EFI_SUCCESS The control bits were read from the serial
- device.
- @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
-
-**/
-EFI_STATUS
-EFIAPI
-GetControlBits (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- OUT UINT32 *Control
- )
-{
- USB_SER_DEV *UsbSerialDevice;
- EFI_STATUS Status;
-
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
-
- *Control = 0;
-
- Status = GetControlBitsInternal (UsbSerialDevice, Control);
-
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- return Status;
-}
-
-/**
- Reads data from a serial device.
-
- @param This[in] Protocol instance pointer.
- @param BufferSize[in, out] On input, the size of the Buffer. On output,
- the amount of data returned in Buffer.
- @param Buffer[out] The buffer to return the data into.
-
- @retval EFI_SUCCESS The data was read.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_TIMEOUT The data write was stopped due to a timeout.
-
-**/
-EFI_STATUS
-EFIAPI
-ReadSerialIo (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
-{
- UINTN Index;
- UINTN RemainingCallerBufferSize;
- USB_SER_DEV *UsbSerialDevice;
- EFI_STATUS Status;
-
-
- if (*BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- if (Buffer == NULL) {
- return EFI_DEVICE_ERROR;
- }
-
- Status = EFI_SUCCESS;
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
-
- //
- // Clear out any data that we already have in our internal buffer
- //
- for (Index = 0; Index < *BufferSize; Index++) {
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- break;
- }
-
- //
- // Still have characters in the buffer to return
- //
- ((UINT8 *)Buffer)[Index] = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];
- UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;
- }
-
- //
- // If we haven't filled the caller's buffer using data that we already had on
- // hand We need to generate an additional USB request to try and fill the
- // caller's buffer
- //
- if (Index != *BufferSize) {
- RemainingCallerBufferSize = *BufferSize - Index;
- Status = ReadDataFromUsb (
- UsbSerialDevice,
- &RemainingCallerBufferSize,
- (VOID *)(((CHAR8 *)Buffer) + Index)
- );
- if (!EFI_ERROR (Status)) {
- *BufferSize = RemainingCallerBufferSize + Index;
- } else {
- *BufferSize = Index;
- }
- }
-
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- //
- // Data buffer has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY flag
- //
- UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
- } else {
- //
- // There is some leftover data, clear EFI_SERIAL_INPUT_BUFFER_EMPTY flag
- //
- UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
- }
- return Status;
-}
-
-/**
- Writes data to a serial device.
-
- @param This[in] Protocol instance pointer.
- @param BufferSize[in, out] On input, the size of the Buffer. On output,
- the amount of data actually written.
- @param Buffer[in] The buffer of data to write
-
- @retval EFI_SUCCESS The data was written.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_TIMEOUT The data write was stopped due to a timeout.
-
-**/
-EFI_STATUS
-EFIAPI
-WriteSerialIo (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
- EFI_TPL Tpl;
-
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
-
- if (UsbSerialDevice->Shutdown) {
- return EFI_DEVICE_ERROR;
- }
-
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
-
- Status = UsbSerialDataTransfer (
- UsbSerialDevice,
- EfiUsbDataOut,
- Buffer,
- BufferSize,
- FTDI_TIMEOUT
- );
-
- gBS->RestoreTPL (Tpl);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_TIMEOUT){
- return Status;
- } else {
- return EFI_DEVICE_ERROR;
- }
- }
-
- return EFI_SUCCESS;
-}