X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OptionRomPkg%2FBus%2FUsb%2FFtdiUsbSerialDxe%2FFtdiUsbSerialDriver.c;fp=OptionRomPkg%2FBus%2FUsb%2FFtdiUsbSerialDxe%2FFtdiUsbSerialDriver.c;h=0000000000000000000000000000000000000000;hp=ac09fae014bfb9a985c9ed7a828d74eb29825065;hb=5347c48016f27061475fdb053e867a06ce73492f;hpb=96ef5a8e30a8da33eaab09f13cc8d752342717a5 diff --git a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c b/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c deleted file mode 100644 index ac09fae014..0000000000 --- a/OptionRomPkg/Bus/Usb/FtdiUsbSerialDxe/FtdiUsbSerialDriver.c +++ /dev/null @@ -1,2580 +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 -SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -// - -// 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; -}