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