2 USB Serial Driver that manages USB to Serial and produces Serial IO Protocol.
4 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
5 Portions Copyright 2012 Ashley DeSimone
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // Tested with VEND_ID 0x0403, DEVICE_ID 0x6001
14 // Driver starts the device with the following values:
15 // 115200, No parity, 8 data bits, 1 stop bit, No Flow control
18 #include "FtdiUsbSerialDriver.h"
21 // Table of supported devices. This is the device information that this
22 // driver was developed with. Add other FTDI devices as needed.
24 USB_DEVICE gUSBDeviceList
[] = {
25 {VID_FTDI
, DID_FTDI_FT232
},
30 // USB Serial Driver Global Variables
32 EFI_DRIVER_BINDING_PROTOCOL gUsbSerialDriverBinding
= {
33 UsbSerialDriverBindingSupported
,
34 UsbSerialDriverBindingStart
,
35 UsbSerialDriverBindingStop
,
42 // Table with the nearest power of 2 for the numbers 0-15
44 UINT8 gRoundedPowersOf2
[16] = { 0, 2, 2, 4, 4, 4, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16 };
47 Check to see if the device path node is the Flow control node
49 @param[in] FlowControl The device path node to be checked
51 @retval TRUE It is the flow control node
52 @retval FALSE It is not the flow control node
56 IsUartFlowControlNode (
57 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
61 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
62 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
63 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
68 Checks the device path to see if it contains flow control.
70 @param[in] DevicePath The device path to be checked
72 @retval TRUE It contains flow control
73 @retval FALSE It does not contain flow control
78 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
81 while (!IsDevicePathEnd (DevicePath
)) {
82 if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH
*) DevicePath
)) {
85 DevicePath
= NextDevicePathNode (DevicePath
);
91 Transfer the data between the device and host.
93 This function transfers the data between the device and host.
94 BOT transfer is composed of three phases: Command, Data, and Status.
95 This is the Data phase.
97 @param UsbBot[in] The USB BOT device
98 @param DataDir[in] The direction of the data
99 @param Data[in, out] The buffer to hold data
100 @param TransLen[in, out] The expected length of the data
101 @param Timeout[in] The time to wait the command to complete
103 @retval EFI_SUCCESS The data is transferred
104 @retval EFI_SUCCESS No data to transfer
105 @retval EFI_NOT_READY The device return NAK to the transfer
106 @retval Others Failed to transfer data
110 UsbSerialDataTransfer (
111 IN USB_SER_DEV
*UsbBot
,
112 IN EFI_USB_DATA_DIRECTION DataDir
,
114 IN OUT UINTN
*TransLen
,
118 EFI_USB_ENDPOINT_DESCRIPTOR
*Endpoint
;
123 // If no data to transfer, just return EFI_SUCCESS.
125 if ((DataDir
== EfiUsbNoData
) || (*TransLen
== 0)) {
130 // Select the endpoint then issue the transfer
132 if (DataDir
== EfiUsbDataIn
) {
133 Endpoint
= &UsbBot
->InEndpointDescriptor
;
135 Endpoint
= &UsbBot
->OutEndpointDescriptor
;
139 Status
= UsbBot
->UsbIo
->UsbBulkTransfer (
141 Endpoint
->EndpointAddress
,
147 if (EFI_ERROR (Status
)) {
148 if (USB_IS_ERROR (Result
, EFI_USB_ERR_NAK
)) {
149 Status
= EFI_NOT_READY
;
151 UsbBot
->Shutdown
= TRUE
; // Fixes infinite loop in older EFI
159 Sets the status values of the Usb Serial Device.
161 @param UsbSerialDevice[in] Handle to the Usb Serial Device to set the status
163 @param StatusBuffer[in] Buffer holding the status values
165 @retval EFI_SUCCESS The status values were read and set correctly
171 IN USB_SER_DEV
*UsbSerialDevice
,
172 IN UINT8
*StatusBuffer
177 Msr
= (StatusBuffer
[0] & MSR_MASK
);
180 // set the Status values to disabled
182 UsbSerialDevice
->StatusValues
.CtsState
= FALSE
;
183 UsbSerialDevice
->StatusValues
.DsrState
= FALSE
;
184 UsbSerialDevice
->StatusValues
.RiState
= FALSE
;
185 UsbSerialDevice
->StatusValues
.SdState
= FALSE
;
188 // Check the values from the status buffer and set the appropriate status
191 if ((Msr
& CTS_MASK
) == CTS_MASK
) {
192 UsbSerialDevice
->StatusValues
.CtsState
= TRUE
;
194 if ((Msr
& DSR_MASK
) == DSR_MASK
) {
195 UsbSerialDevice
->StatusValues
.DsrState
= TRUE
;
197 if ((Msr
& RI_MASK
) == RI_MASK
) {
198 UsbSerialDevice
->StatusValues
.RiState
= TRUE
;
200 if ((Msr
& SD_MASK
) == SD_MASK
) {
201 UsbSerialDevice
->StatusValues
.SdState
= TRUE
;
207 Initiates a read operation on the Usb Serial Device.
209 @param UsbSerialDevice[in] Handle to the USB device to read
210 @param BufferSize[in, out] On input, the size of the Buffer. On output,
211 the amount of data returned in Buffer.
212 Setting this to zero will initiate a read
213 and store all data returned in the internal
215 @param Buffer [out] The buffer to return the data into.
217 @retval EFI_SUCCESS The data was read.
218 @retval EFI_DEVICE_ERROR The device reported an error.
219 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
225 IN USB_SER_DEV
*UsbSerialDevice
,
226 IN OUT UINTN
*BufferSize
,
231 UINTN ReadBufferSize
;
235 UINT8 StatusBuffer
[2]; // buffer to store the status bytes
237 ReadBufferSize
= 512;
238 ReadBuffer
= &(UsbSerialDevice
->ReadBuffer
[0]);
240 if (UsbSerialDevice
->Shutdown
) {
241 return EFI_DEVICE_ERROR
;
244 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
246 Status
= UsbSerialDataTransfer (
251 FTDI_TIMEOUT
*2 //Padded because timers won't be exactly aligned
253 if (EFI_ERROR (Status
)) {
254 gBS
->RestoreTPL (Tpl
);
255 if (Status
== EFI_TIMEOUT
) {
258 return EFI_DEVICE_ERROR
;
263 // Store the status bytes in the status buffer
265 for (Index
= 0; Index
< 2; Index
++) {//only the first 2 bytes are status bytes
266 StatusBuffer
[Index
] = ReadBuffer
[Index
];
269 // update the statusvalue field of the usbserialdevice
271 Status
= SetStatusInternal (UsbSerialDevice
, StatusBuffer
);
272 if (Status
!= EFI_SUCCESS
) {
276 // Store the read data in the read buffer, start at 2 to ignore status bytes
278 for (Index
= 2; Index
< ReadBufferSize
; Index
++) {
279 if (((UsbSerialDevice
->DataBufferTail
+ 1) % SW_FIFO_DEPTH
) == UsbSerialDevice
->DataBufferHead
) {
282 if (ReadBuffer
[Index
] == 0x00) {
284 // This is null, do not add
287 UsbSerialDevice
->DataBuffer
[UsbSerialDevice
->DataBufferTail
] = ReadBuffer
[Index
];
288 UsbSerialDevice
->DataBufferTail
= (UsbSerialDevice
->DataBufferTail
+ 1) % SW_FIFO_DEPTH
;
293 // Read characters out of the buffer to satisfy caller's request.
295 for (Index
= 0; Index
< *BufferSize
; Index
++) {
296 if (UsbSerialDevice
->DataBufferHead
== UsbSerialDevice
->DataBufferTail
) {
300 // Still have characters in the buffer to return
302 ((UINT8
*)Buffer
)[Index
] = UsbSerialDevice
->DataBuffer
[UsbSerialDevice
->DataBufferHead
];
303 UsbSerialDevice
->DataBufferHead
= (UsbSerialDevice
->DataBufferHead
+ 1) % SW_FIFO_DEPTH
;
306 // Return actual number of bytes returned.
309 gBS
->RestoreTPL (Tpl
);
314 Sets the initial status values of the Usb Serial Device by reading the status
315 bytes from the device.
317 @param UsbSerialDevice[in] Handle to the Usb Serial Device that needs its
318 initial status values set
320 @retval EFI_SUCCESS The status bytes were read successfully and the
321 initial status values were set correctly
322 @retval EFI_TIMEOUT The read of the status bytes was stopped due to a
324 @retval EFI_DEVICE_ERROR The device reported an error during the read of
331 IN USB_SER_DEV
*UsbSerialDevice
337 UINT8 StatusBuffer
[2];
339 Status
= EFI_UNSUPPORTED
;
340 BufferSize
= sizeof (StatusBuffer
);
342 if (UsbSerialDevice
->Shutdown
) {
343 return EFI_DEVICE_ERROR
;
346 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
348 Status
= UsbSerialDataTransfer (
353 40 //Slightly more than 2x the FTDI polling frequency to make sure that data will be returned
356 Status
= SetStatusInternal (UsbSerialDevice
, StatusBuffer
);
358 gBS
->RestoreTPL (Tpl
);
364 UsbSerialDriverCheckInput.
365 attempts to read data in from the device periodically, stores any read data
366 and updates the control attributes.
369 @param Context[in]....The current instance of the USB serial device
374 UsbSerialDriverCheckInput (
380 USB_SER_DEV
*UsbSerialDevice
;
382 UsbSerialDevice
= (USB_SER_DEV
*)Context
;
384 if (UsbSerialDevice
->DataBufferHead
== UsbSerialDevice
->DataBufferTail
) {
386 // Data buffer is empty, try to read from device
389 ReadDataFromUsb (UsbSerialDevice
, &BufferSize
, NULL
);
390 if (UsbSerialDevice
->DataBufferHead
== UsbSerialDevice
->DataBufferTail
) {
392 // Data buffer still has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY
395 UsbSerialDevice
->ControlBits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
398 // Read has returned some data, clear the EFI_SERIAL_INPUT_BUFFER_EMPTY
401 UsbSerialDevice
->ControlBits
&= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY
);
405 // Data buffer has data, no read attempt required
407 UsbSerialDevice
->ControlBits
&= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY
);
412 Encodes the baud rate into the format expected by the Ftdi device.
414 @param BaudRate[in] The baudrate to be set on the device
415 @param EncodedBaudRate[out] The baud rate encoded in the format
416 expected by the Ftdi device
418 @return EFI_SUCCESS Baudrate encoding was calculated
420 @return EFI_INVALID_PARAMETER An invalid value of BaudRate was received
425 EncodeBaudRateForFtdi (
427 OUT UINT16
*EncodedBaudRate
431 UINT32 AdjustedFrequency
;
435 // Check to make sure we won't get an integer overflow
437 if ((BaudRate
< 178) || ( BaudRate
> ((FTDI_UART_FREQUENCY
* 100) / 97))) {
438 return EFI_INVALID_PARAMETER
;
442 // Baud Rates of 2000000 and 3000000 are special cases
444 if ((BaudRate
>= FTDI_SPECIAL_CASE_300_MIN
) && (BaudRate
<= FTDI_SPECIAL_CASE_300_MAX
)) {
445 *EncodedBaudRate
= 0;
448 if ((BaudRate
>= FTDI_SPECIAL_CASE_200_MIN
) && (BaudRate
<= FTDI_SPECIAL_CASE_200_MAX
)) {
449 *EncodedBaudRate
= 1;
456 Divisor
= (FTDI_UART_FREQUENCY
<< 4) / (UINT32
)BaudRate
;
459 // Round the last 4 bits to the nearest power of 2
461 Divisor
= (Divisor
& ~(0xF)) + (gRoundedPowersOf2
[Divisor
& 0xF]);
464 // Check to make sure computed divisor is within
465 // the min and max that FTDI controller will accept
467 if (Divisor
< FTDI_MIN_DIVISOR
) {
468 Divisor
= FTDI_MIN_DIVISOR
;
469 } else if (Divisor
> FTDI_MAX_DIVISOR
) {
470 Divisor
= FTDI_MAX_DIVISOR
;
474 // Check to make sure the frequency that the FTDI chip will need to
475 // generate to attain the requested Baud Rate is within 3% of the
476 // 3MHz clock frequency that the FTDI chip runs at.
478 // (3MHz * 1600) / 103 = 46601941
479 // (3MHz * 1600) / 97 = 49484536
481 AdjustedFrequency
= (((UINT32
)BaudRate
) * Divisor
);
482 if ((AdjustedFrequency
< FTDI_MIN_FREQUENCY
) || (AdjustedFrequency
> FTDI_MAX_FREQUENCY
)) {
483 return EFI_INVALID_PARAMETER
;
487 // Encode the Divisor into the format FTDI expects
489 Result
= (UINT16
)(Divisor
>> 4);
490 if ((Divisor
& 0x8) != 0) {
492 } else if ((Divisor
& 0x4) != 0) {
494 } else if ((Divisor
& 0x2) != 0) {
498 *EncodedBaudRate
= Result
;
503 Uses USB I/O to check whether the device is a USB Serial device.
505 @param UsbIo[in] Pointer to a USB I/O protocol instance.
507 @retval TRUE Device is a USB Serial device.
508 @retval FALSE Device is a not USB Serial device.
513 IN EFI_USB_IO_PROTOCOL
*UsbIo
517 EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor
;
523 // Get the default device descriptor
525 Status
= UsbIo
->UsbGetDeviceDescriptor (
529 if (EFI_ERROR (Status
)) {
535 while (gUSBDeviceList
[Index
].VendorId
!= 0 &&
536 gUSBDeviceList
[Index
].DeviceId
!= 0 &&
538 if (DeviceDescriptor
.IdProduct
== gUSBDeviceList
[Index
].DeviceId
&&
539 DeviceDescriptor
.IdVendor
== gUSBDeviceList
[Index
].VendorId
){
541 // Checks to see if a string descriptor can be pulled from the device in
542 // the selected language. If not False is returned indicating that this
543 // is not a Usb Serial Device that can be managegd by this driver
546 Status
= UsbIo
->UsbGetStringDescriptor (
548 USB_US_LANG_ID
, // LANGID selector, should make this
549 // more robust to verify lang support
551 DeviceDescriptor
.StrManufacturer
,
554 if (StrMfg
!= NULL
) {
557 if (EFI_ERROR (Status
)) {
568 Internal function that sets the Data Bits, Stop Bits and Parity values on the
569 Usb Serial Device with a single usb control transfer.
571 @param UsbIo[in] Usb Io Protocol instance pointer
572 @param DataBits[in] The data bits value to be set on the Usb
574 @param Parity[in] The parity type that will be set on the Usb
576 @param StopBits[in] The stop bits type that will be set on the
578 @param LastSettings[in] A pointer to the Usb Serial Device's
579 PREVIOUS_ATTRIBUTES item
581 @retval EFI_SUCCESS The data items were correctly set on the
583 @retval EFI_INVALID_PARAMETER An invalid data parameter or an invalid
584 combination or parameters was used
585 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
586 the data values were unable to be set
592 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
594 IN EFI_PARITY_TYPE Parity
,
595 IN EFI_STOP_BITS_TYPE StopBits
,
596 IN PREVIOUS_ATTRIBUTES
*LastSettings
600 EFI_USB_DEVICE_REQUEST DevReq
;
602 UINT8 ConfigurationValue
;
605 // Since data bits settings of 6,7,8 cannot be set with a stop bits setting of
606 // 1.5 check to see if this happens when the values of last settings are used
608 if ((DataBits
== 0) && (StopBits
== OneFiveStopBits
)) {
609 if ((LastSettings
->DataBits
== 6) || (LastSettings
->DataBits
== 7) || (LastSettings
->DataBits
== 8)) {
610 return EFI_INVALID_PARAMETER
;
612 } else if ((StopBits
== DefaultStopBits
) && ((DataBits
== 6) || (DataBits
== 7) || (DataBits
== 8))) {
613 if (LastSettings
->StopBits
== OneFiveStopBits
) {
614 return EFI_INVALID_PARAMETER
;
616 } else if ((DataBits
== 0) && (StopBits
== DefaultStopBits
)) {
617 if (LastSettings
->StopBits
== OneFiveStopBits
) {
618 if ((LastSettings
->DataBits
== 6) || (LastSettings
->DataBits
== 7) || (LastSettings
->DataBits
== 8)) {
619 return EFI_INVALID_PARAMETER
;
625 // set the DevReq.Value for the usb control transfer to the correct value
626 // based on the seleceted number of data bits if there is an invalid number of
627 // data bits requested return EFI_INVALID_PARAMETER
629 if (((DataBits
< 5 ) || (DataBits
> 8)) && (DataBits
!= 0)) {
630 return EFI_INVALID_PARAMETER
;
634 // use the value of LastDataBits
636 DevReq
.Value
= SET_DATA_BITS (LastSettings
->DataBits
);
639 // use the value of DataBits
641 DevReq
.Value
= SET_DATA_BITS (DataBits
);
647 if (Parity
== DefaultParity
) {
648 Parity
= LastSettings
->Parity
;
651 if (Parity
== NoParity
) {
652 DevReq
.Value
|= SET_PARITY_NONE
;
653 } else if (Parity
== EvenParity
) {
654 DevReq
.Value
|= SET_PARITY_EVEN
;
655 } else if (Parity
== OddParity
){
656 DevReq
.Value
|= SET_PARITY_ODD
;
657 } else if (Parity
== MarkParity
) {
658 DevReq
.Value
|= SET_PARITY_MARK
;
659 } else if (Parity
== SpaceParity
) {
660 DevReq
.Value
|= SET_PARITY_SPACE
;
666 if (StopBits
== DefaultStopBits
) {
667 StopBits
= LastSettings
->StopBits
;
670 if (StopBits
== OneStopBit
) {
671 DevReq
.Value
|= SET_STOP_BITS_1
;
672 } else if (StopBits
== OneFiveStopBits
) {
673 DevReq
.Value
|= SET_STOP_BITS_15
;
674 } else if (StopBits
== TwoStopBits
) {
675 DevReq
.Value
|= SET_STOP_BITS_2
;
679 // set the rest of the DevReq parameters and perform the usb control transfer
680 // to set the data bits on the device
682 DevReq
.Request
= FTDI_COMMAND_SET_DATA
;
683 DevReq
.RequestType
= USB_REQ_TYPE_VENDOR
;
684 DevReq
.Index
= FTDI_PORT_IDENTIFIER
;
685 DevReq
.Length
= 0; // indicates that there is no data phase in this request
687 Status
= UsbIo
->UsbControlTransfer (
696 if (EFI_ERROR (Status
)) {
702 if ((Status
!= EFI_INVALID_PARAMETER
) || (Status
!= EFI_DEVICE_ERROR
)) {
703 return EFI_DEVICE_ERROR
;
710 Internal function that sets the baudrate on the Usb Serial Device.
712 @param UsbIo[in] Usb Io Protocol instance pointer
713 @param BaudRate[in] The baudrate value to be set on the device.
714 If this value is 0 the value of LastBaudRate
716 @param LastBaudRate[in] The baud rate value that was previously set
717 on the Usb Serial Device
719 @retval EFI_SUCCESS The baudrate was set succesfully
720 @retval EFI_INVALID_PARAMETER An invalid baudrate was used
721 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
722 the baudrate was unable to be set
727 SetBaudRateInternal (
728 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
730 IN UINT64 LastBaudRate
734 EFI_USB_DEVICE_REQUEST DevReq
;
736 UINT8 ConfigurationValue
;
737 UINT16 EncodedBaudRate
;
740 Tpl
= gBS
->RaiseTPL(TPL_NOTIFY
);
743 // set the value of DevReq.Value based on the value of BaudRate
744 // if 0 is selected as baud rate use the value of LastBaudRate
747 Status
= EncodeBaudRateForFtdi (LastBaudRate
, &EncodedBaudRate
);
748 if (EFI_ERROR (Status
)) {
749 gBS
->RestoreTPL (Tpl
);
751 // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
756 DevReq
.Value
= EncodedBaudRate
;
758 Status
= EncodeBaudRateForFtdi (BaudRate
, &EncodedBaudRate
);
759 if (EFI_ERROR (Status
)) {
760 gBS
->RestoreTPL (Tpl
);
762 // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
767 DevReq
.Value
= EncodedBaudRate
;
771 // set the remaining parameters of DevReq and perform the usb control transfer
774 DevReq
.Request
= FTDI_COMMAND_SET_BAUDRATE
;
775 DevReq
.RequestType
= USB_REQ_TYPE_VENDOR
;
776 DevReq
.Index
= FTDI_PORT_IDENTIFIER
;
777 DevReq
.Length
= 0; // indicates that there is no data phase in this request
779 Status
= UsbIo
->UsbControlTransfer (
788 if (EFI_ERROR (Status
)) {
791 gBS
->RestoreTPL (Tpl
);
795 gBS
->RestoreTPL (Tpl
);
796 if ((Status
!= EFI_INVALID_PARAMETER
) || (Status
!= EFI_DEVICE_ERROR
)) {
797 return EFI_DEVICE_ERROR
;
804 Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
805 data bits, and stop bits on a serial device.
807 @param UsbSerialDevice[in] Pointer to the current instance of the USB Serial
809 @param BaudRate[in] The requested baud rate. A BaudRate value of 0
810 will use the device's default interface speed.
811 @param ReveiveFifoDepth[in] The requested depth of the FIFO on the receive
812 side of the serial interface. A ReceiveFifoDepth
813 value of 0 will use the device's default FIFO
815 @param Timeout[in] The requested time out for a single character in
816 microseconds.This timeout applies to both the
817 transmit and receive side of the interface.A
818 Timeout value of 0 will use the device's default
820 @param Parity[in] The type of parity to use on this serial device.
821 A Parity value of DefaultParity will use the
822 device's default parity value.
823 @param DataBits[in] The number of data bits to use on the serial
824 device. A DataBits value of 0 will use the
825 device's default data bit setting.
826 @param StopBits[in] The number of stop bits to use on this serial
827 device. A StopBits value of DefaultStopBits will
828 use the device's default number of stop bits.
830 @retval EFI_SUCCESS The attributes were set
831 @retval EFI_DEVICE_ERROR The attributes were not able to be set
836 SetAttributesInternal (
837 IN USB_SER_DEV
*UsbSerialDevice
,
839 IN UINT32 ReceiveFifoDepth
,
841 IN EFI_PARITY_TYPE Parity
,
843 IN EFI_STOP_BITS_TYPE StopBits
848 UART_DEVICE_PATH
*Uart
;
849 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
851 Status
= EFI_UNSUPPORTED
;
852 Tpl
= gBS
->RaiseTPL(TPL_NOTIFY
);
856 // check for invalid combinations of parameters
858 if (((DataBits
>= 6) && (DataBits
<= 8)) && (StopBits
== OneFiveStopBits
)) {
859 return EFI_INVALID_PARAMETER
;
863 // set data bits, parity and stop bits
865 Status
= SetDataInternal (
866 UsbSerialDevice
->UsbIo
,
870 &(UsbSerialDevice
->LastSettings
)
872 if (EFI_ERROR (Status
)) {
878 Status
= SetBaudRateInternal (
879 UsbSerialDevice
->UsbIo
,
881 UsbSerialDevice
->LastSettings
.BaudRate
883 if (EFI_ERROR (Status
)){
888 // update the values of UsbSerialDevice->LastSettings and UsbSerialDevice->SerialIo.Mode
891 UsbSerialDevice
->LastSettings
.BaudRate
= UsbSerialDevice
->LastSettings
.BaudRate
;
892 UsbSerialDevice
->SerialIo
.Mode
->BaudRate
= UsbSerialDevice
->LastSettings
.BaudRate
;
894 UsbSerialDevice
->LastSettings
.BaudRate
= BaudRate
;
895 UsbSerialDevice
->SerialIo
.Mode
->BaudRate
= BaudRate
;
898 UsbSerialDevice
->LastSettings
.Timeout
= FTDI_TIMEOUT
;
899 UsbSerialDevice
->LastSettings
.ReceiveFifoDepth
= FTDI_MAX_RECEIVE_FIFO_DEPTH
;
901 if (Parity
== DefaultParity
) {
902 UsbSerialDevice
->LastSettings
.Parity
= UsbSerialDevice
->LastSettings
.Parity
;
903 UsbSerialDevice
->SerialIo
.Mode
->Parity
= UsbSerialDevice
->LastSettings
.Parity
;
905 UsbSerialDevice
->LastSettings
.Parity
= Parity
;
906 UsbSerialDevice
->SerialIo
.Mode
->Parity
= Parity
;
909 UsbSerialDevice
->LastSettings
.DataBits
= UsbSerialDevice
->LastSettings
.DataBits
;
910 UsbSerialDevice
->SerialIo
.Mode
->DataBits
= UsbSerialDevice
->LastSettings
.DataBits
;
912 UsbSerialDevice
->LastSettings
.DataBits
= DataBits
;
913 UsbSerialDevice
->SerialIo
.Mode
->DataBits
= DataBits
;
915 if (StopBits
== DefaultStopBits
) {
916 UsbSerialDevice
->LastSettings
.StopBits
= UsbSerialDevice
->LastSettings
.StopBits
;
917 UsbSerialDevice
->SerialIo
.Mode
->StopBits
= UsbSerialDevice
->LastSettings
.StopBits
;
919 UsbSerialDevice
->LastSettings
.StopBits
= StopBits
;
920 UsbSerialDevice
->SerialIo
.Mode
->StopBits
= StopBits
;
924 // See if the device path node has changed
926 if (UsbSerialDevice
->UartDevicePath
.BaudRate
== BaudRate
&&
927 UsbSerialDevice
->UartDevicePath
.DataBits
== DataBits
&&
928 UsbSerialDevice
->UartDevicePath
.StopBits
== StopBits
&&
929 UsbSerialDevice
->UartDevicePath
.Parity
== Parity
931 gBS
->RestoreTPL (Tpl
);
936 // Update the device path
938 UsbSerialDevice
->UartDevicePath
.BaudRate
= BaudRate
;
939 UsbSerialDevice
->UartDevicePath
.DataBits
= DataBits
;
940 UsbSerialDevice
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
941 UsbSerialDevice
->UartDevicePath
.Parity
= (UINT8
) Parity
;
943 Status
= EFI_SUCCESS
;
944 if (UsbSerialDevice
->ControllerHandle
!= NULL
) {
945 RemainingDevicePath
= UsbSerialDevice
->DevicePath
;
946 while (!IsDevicePathEnd (RemainingDevicePath
)) {
947 Uart
= (UART_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
948 if (Uart
->Header
.Type
== MESSAGING_DEVICE_PATH
&&
949 Uart
->Header
.SubType
== MSG_UART_DP
&&
950 sizeof (UART_DEVICE_PATH
) == DevicePathNodeLength ((EFI_DEVICE_PATH
*) Uart
)) {
951 Uart
->BaudRate
= BaudRate
;
952 Uart
->DataBits
= DataBits
;
953 Uart
->StopBits
= (UINT8
)StopBits
;
954 Uart
->Parity
= (UINT8
) Parity
;
957 RemainingDevicePath
= NextDevicePathNode (RemainingDevicePath
);
961 gBS
->RestoreTPL (Tpl
);
965 gBS
->RestoreTPL (Tpl
);
966 if ((Status
!= EFI_INVALID_PARAMETER
) || (Status
!= EFI_DEVICE_ERROR
)) {
967 return EFI_DEVICE_ERROR
;
974 Internal function that performs a Usb Control Transfer to set the flow control
975 on the Usb Serial Device.
977 @param UsbIo[in] Usb Io Protocol instance pointer
978 @param FlowControlEnable[in] Data on the Enable/Disable status of Flow
979 Control on the Usb Serial Device
981 @retval EFI_SUCCESS The flow control was set on the Usb Serial
983 @retval EFI_INVALID_PARAMETER An invalid flow control value was used
984 @retval EFI_EFI_UNSUPPORTED The operation is not supported
985 @retval EFI_DEVICE_ERROR The device is not functioning correctly
990 SetFlowControlInternal (
991 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
992 IN BOOLEAN FlowControlEnable
996 EFI_USB_DEVICE_REQUEST DevReq
;
998 UINT8 ConfigurationValue
;
1001 // set DevReq.Value based on the value of FlowControlEnable
1003 if (!FlowControlEnable
) {
1004 DevReq
.Value
= NO_FLOW_CTRL
;
1006 if (FlowControlEnable
) {
1007 DevReq
.Value
= XON_XOFF_CTRL
;
1010 // set the remaining DevReq parameters and perform the usb control transfer to
1011 // set the flow control on the device
1013 DevReq
.Request
= FTDI_COMMAND_SET_FLOW_CTRL
;
1014 DevReq
.RequestType
= USB_REQ_TYPE_VENDOR
;
1015 DevReq
.Index
= FTDI_PORT_IDENTIFIER
;
1016 DevReq
.Length
= 0; // indicates that this transfer has no data phase
1017 Status
= UsbIo
->UsbControlTransfer (
1022 &ConfigurationValue
,
1026 if (EFI_ERROR (Status
)) {
1033 if ((Status
!= EFI_INVALID_PARAMETER
) ||
1034 (Status
!= EFI_DEVICE_ERROR
) ||
1035 (Status
!= EFI_UNSUPPORTED
) ) {
1036 return EFI_DEVICE_ERROR
;
1043 Internal function that performs a Usb Control Transfer to set the Dtr value on
1044 the Usb Serial Device.
1046 @param UsbIo[in] Usb Io Protocol instance pointer
1047 @param DtrEnable[in] Data on the Enable/Disable status of the
1048 Dtr for the Usb Serial Device
1050 @retval EFI_SUCCESS The Dtr value was set on the Usb Serial
1052 @retval EFI_INVALID_PARAMETER An invalid Dtr value was used
1053 @retval EFI_UNSUPPORTED The operation is not supported
1054 @retval EFI_DEVICE_ERROR The device is not functioning correctly
1060 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
1061 IN BOOLEAN DtrEnable
1065 EFI_USB_DEVICE_REQUEST DevReq
;
1067 UINT8 ConfigurationValue
;
1070 // set the value of DevReq.Value based on the value of DtrEnable
1073 DevReq
.Value
= SET_DTR_LOW
;
1076 DevReq
.Value
= SET_DTR_HIGH
;
1079 // set the remaining attributes of DevReq and perform the usb control transfer
1080 // to set the device
1082 DevReq
.Request
= FTDI_COMMAND_MODEM_CTRL
;
1083 DevReq
.RequestType
= USB_REQ_TYPE_VENDOR
;
1084 DevReq
.Index
= FTDI_PORT_IDENTIFIER
;
1085 DevReq
.Length
= 0; // indicates that there is no data phase in this transfer
1087 Status
= UsbIo
->UsbControlTransfer (
1092 &ConfigurationValue
,
1096 if (EFI_ERROR (Status
)) {
1102 if ((Status
!= EFI_INVALID_PARAMETER
) ||
1103 (Status
!= EFI_DEVICE_ERROR
) ||
1104 (Status
!= EFI_UNSUPPORTED
) ) {
1105 return EFI_DEVICE_ERROR
;
1112 Internal function that performs a Usb Control Transfer to set the Dtr value on
1113 the Usb Serial Device.
1115 @param UsbIo[in] Usb Io Protocol instance pointer
1116 @param RtsEnable[in] Data on the Enable/Disable status of the
1117 Rts for the Usb Serial Device
1119 @retval EFI_SUCCESS The Rts value was set on the Usb Serial
1121 @retval EFI_INVALID_PARAMETER An invalid Rts value was used
1122 @retval EFI_UNSUPPORTED The operation is not supported
1123 @retval EFI_DEVICE_ERROR The device is not functioning correctly
1129 IN EFI_USB_IO_PROTOCOL
*UsbIo
,
1130 IN BOOLEAN RtsEnable
1134 EFI_USB_DEVICE_REQUEST DevReq
;
1136 UINT8 ConfigurationValue
;
1139 // set DevReq.Value based on the value of RtsEnable
1142 DevReq
.Value
= SET_RTS_LOW
;
1145 DevReq
.Value
= SET_RTS_HIGH
;
1149 // set the remaining parameters of DevReq and perform the usb control transfer
1150 // to set the values on the device
1152 DevReq
.Request
= FTDI_COMMAND_MODEM_CTRL
;
1153 DevReq
.RequestType
= USB_REQ_TYPE_VENDOR
;
1154 DevReq
.Index
= FTDI_PORT_IDENTIFIER
;
1155 DevReq
.Length
= 0; // indicates that there is no data phase in this request
1157 Status
= UsbIo
->UsbControlTransfer (
1162 &ConfigurationValue
,
1166 if (EFI_ERROR (Status
)) {
1173 if ((Status
!= EFI_INVALID_PARAMETER
) ||
1174 (Status
!= EFI_DEVICE_ERROR
) ||
1175 (Status
!= EFI_UNSUPPORTED
) ) {
1176 return EFI_DEVICE_ERROR
;
1183 Internal function that checks for valid control values and sets the control
1184 bits on the Usb Serial Device.
1186 @param UsbSerialDevice[in] Handle to the Usb Serial Device whose
1187 control bits are being set
1188 @param Control[in] The control value passed to the function
1189 that contains the values of the control
1190 bits that are being set
1192 @retval EFI_SUCCESS The control bits were set on the Usb Serial
1194 @retval EFI_INVALID_PARAMETER An invalid control value was encountered
1195 @retval EFI_EFI_UNSUPPORTED The operation is not supported
1196 @retval EFI_DEVICE_ERROR The device is not functioning correctly
1201 SetControlBitsInternal (
1202 IN USB_SER_DEV
*UsbSerialDevice
,
1203 IN CONTROL_BITS
*Control
1207 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
1208 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
1211 // check for invalid control parameters hardware and software loopback enabled
1212 // must always be set to FALSE
1214 Control
->HardwareLoopBack
= FALSE
;
1215 Control
->SoftwareLoopBack
= FALSE
;
1218 // set hardware flow control
1220 Status
= SetFlowControlInternal (
1221 UsbSerialDevice
->UsbIo
,
1222 Control
->HardwareFlowControl
1224 if (EFI_ERROR (Status
)) {
1231 Status
= SetDtrInternal (UsbSerialDevice
->UsbIo
, Control
->DtrState
);
1232 if (EFI_ERROR (Status
)) {
1239 Status
= SetRtsInternal (UsbSerialDevice
->UsbIo
, Control
->RtsState
);
1240 if (EFI_ERROR (Status
)){
1245 // update the remaining control values for UsbSerialDevice->ControlValues
1247 UsbSerialDevice
->ControlValues
.DtrState
= Control
->DtrState
;
1248 UsbSerialDevice
->ControlValues
.RtsState
= Control
->RtsState
;
1249 UsbSerialDevice
->ControlValues
.HardwareFlowControl
= Control
->HardwareFlowControl
;
1250 UsbSerialDevice
->ControlValues
.HardwareLoopBack
= FALSE
;
1251 UsbSerialDevice
->ControlValues
.SoftwareLoopBack
= FALSE
;
1253 Status
= EFI_SUCCESS
;
1255 // Update the device path to have the correct flow control values
1257 if (UsbSerialDevice
->ControllerHandle
!= NULL
) {
1258 RemainingDevicePath
= UsbSerialDevice
->DevicePath
;
1259 while (!IsDevicePathEnd (RemainingDevicePath
)) {
1260 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
1261 if (FlowControl
->Header
.Type
== MESSAGING_DEVICE_PATH
&&
1262 FlowControl
->Header
.SubType
== MSG_VENDOR_DP
&&
1263 sizeof (UART_FLOW_CONTROL_DEVICE_PATH
) == DevicePathNodeLength ((EFI_DEVICE_PATH
*) FlowControl
)){
1264 if (UsbSerialDevice
->ControlValues
.HardwareFlowControl
== TRUE
) {
1265 FlowControl
->FlowControlMap
= UART_FLOW_CONTROL_HARDWARE
;
1266 } else if (UsbSerialDevice
->ControlValues
.HardwareFlowControl
== FALSE
) {
1267 FlowControl
->FlowControlMap
= 0;
1271 RemainingDevicePath
= NextDevicePathNode (RemainingDevicePath
);
1278 if ((Status
!= EFI_INVALID_PARAMETER
) ||
1279 (Status
!= EFI_DEVICE_ERROR
) ||
1280 (Status
!= EFI_UNSUPPORTED
) ) {
1281 return EFI_DEVICE_ERROR
;
1288 Internal function that calculates the Control value used by GetControlBits()
1289 based on the status and control values of the Usb Serial Device.
1291 @param UsbSerialDevice[in] Handle to the Usb Serial Devie whose status
1292 and control values are being used to set
1294 @param Control[out] On output the formated value of Control
1295 that has been calculated based on the
1296 control and status values of the Usb Serial
1299 @retval EFI_SUCCESS The value of Control was successfully
1305 GetControlBitsInternal (
1306 IN USB_SER_DEV
*UsbSerialDevice
,
1313 // Check the values of UsbSerialDevice->Status Values and modify control
1314 // accordingly these values correspond to the modem status register
1316 if (UsbSerialDevice
->StatusValues
.CtsState
) {
1317 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
1319 if (UsbSerialDevice
->StatusValues
.DsrState
) {
1320 *Control
|= EFI_SERIAL_DATA_SET_READY
;
1322 if (UsbSerialDevice
->StatusValues
.RiState
) {
1323 *Control
|= EFI_SERIAL_RING_INDICATE
;
1325 if (UsbSerialDevice
->StatusValues
.SdState
) {
1326 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
1330 // check the values of UsbSerialDevice->ControlValues and modify control
1331 // accordingly these values correspond to the values of the Modem Control
1334 if (UsbSerialDevice
->ControlValues
.DtrState
) {
1335 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1337 if (UsbSerialDevice
->ControlValues
.RtsState
) {
1338 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1340 if (UsbSerialDevice
->ControlValues
.HardwareLoopBack
) {
1341 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1343 if (UsbSerialDevice
->ControlValues
.HardwareFlowControl
) {
1344 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1347 // check if the buffer is empty since only one is being used if it is empty
1348 // set both the receive and transmit buffers to empty
1350 if (UsbSerialDevice
->DataBufferHead
== UsbSerialDevice
->DataBufferTail
) {
1351 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
1352 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1355 // check for software loopback enable in UsbSerialDevice->ControlValues
1357 if (UsbSerialDevice
->ControlValues
.SoftwareLoopBack
) {
1358 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1365 Resets the USB Serial Device
1367 This function is the internal method for resetting the device and is called by
1370 @param UsbSerialDevice[in] A pointer to the USB Serial device
1372 @retval EFI_SUCCESS The device was reset
1373 @retval EFI_DEVICE_ERROR The device could not be reset
1379 IN USB_SER_DEV
*UsbSerialDevice
1383 EFI_USB_DEVICE_REQUEST DevReq
;
1384 UINT8 ConfigurationValue
;
1387 DevReq
.Request
= FTDI_COMMAND_RESET_PORT
;
1388 DevReq
.RequestType
= USB_REQ_TYPE_VENDOR
;
1389 DevReq
.Value
= RESET_PORT_PURGE_RX
;
1390 DevReq
.Index
= FTDI_PORT_IDENTIFIER
;
1391 DevReq
.Length
= 0; //indicates that there is not data phase in this request
1393 Status
= UsbSerialDevice
->UsbIo
->UsbControlTransfer (
1394 UsbSerialDevice
->UsbIo
,
1398 &ConfigurationValue
,
1402 if (EFI_ERROR (Status
)) {
1403 return EFI_DEVICE_ERROR
;
1406 DevReq
.Request
= FTDI_COMMAND_RESET_PORT
;
1407 DevReq
.RequestType
= USB_REQ_TYPE_VENDOR
;
1408 DevReq
.Value
= RESET_PORT_PURGE_TX
;
1409 DevReq
.Index
= FTDI_PORT_IDENTIFIER
;
1410 DevReq
.Length
= 0; //indicates that there is no data phase in this request
1412 Status
= UsbSerialDevice
->UsbIo
->UsbControlTransfer (
1413 UsbSerialDevice
->UsbIo
,
1417 &ConfigurationValue
,
1421 if (EFI_ERROR (Status
)) {
1422 return EFI_DEVICE_ERROR
;
1428 Entrypoint of USB Serial Driver.
1430 This function is the entrypoint of USB Serial Driver. It installs
1431 Driver Binding Protocols together with Component Name Protocols.
1433 @param ImageHandle[in] The firmware allocated handle for the EFI image.
1434 @param SystemTable[in] A pointer to the EFI System Table.
1436 @retval EFI_SUCCESS The entry point is executed successfully.
1441 FtdiUsbSerialEntryPoint (
1442 IN EFI_HANDLE ImageHandle
,
1443 IN EFI_SYSTEM_TABLE
*SystemTable
1448 Status
= EfiLibInstallDriverBindingComponentName2 (
1451 &gUsbSerialDriverBinding
,
1453 &gUsbSerialComponentName
,
1454 &gUsbSerialComponentName2
1456 ASSERT_EFI_ERROR (Status
);
1461 Unload function for the Usb Serial Driver.
1463 @param ImageHandle[in] The allocated handle for the EFI image
1465 @retval EFI_SUCCESS The driver was unloaded successfully
1469 FtdiUsbSerialUnload (
1470 IN EFI_HANDLE ImageHandle
1474 EFI_HANDLE
*HandleBuffer
;
1479 // Retrieve all handles in the handle database
1481 Status
= gBS
->LocateHandleBuffer (
1488 if (EFI_ERROR (Status
)) {
1493 // Disconnect the driver from the handles in the handle database
1495 for (Index
= 0; Index
< HandleCount
; Index
++) {
1496 Status
= gBS
->DisconnectController (
1497 HandleBuffer
[Index
],
1504 // Free the handle array
1506 FreePool (HandleBuffer
);
1509 // Uninstall protocols installed by the driver in its entrypoint
1511 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1513 &gEfiDriverBindingProtocolGuid
,
1514 &gUsbSerialDriverBinding
,
1515 &gEfiComponentNameProtocolGuid
,
1516 &gUsbSerialComponentName
,
1517 &gEfiComponentName2ProtocolGuid
,
1518 &gUsbSerialComponentName2
,
1521 if (EFI_ERROR (Status
)) {
1529 Check whether USB Serial driver supports this device.
1531 @param This[in] The USB Serial driver binding protocol.
1532 @param Controller[in] The controller handle to check.
1533 @param RemainingDevicePath[in] The remaining device path.
1535 @retval EFI_SUCCESS The driver supports this controller.
1536 @retval other This device isn't supported.
1541 UsbSerialDriverBindingSupported (
1542 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1543 IN EFI_HANDLE Controller
,
1544 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1548 EFI_USB_IO_PROTOCOL
*UsbIo
;
1549 UART_DEVICE_PATH
*UartNode
;
1550 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControlNode
;
1553 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
1554 BOOLEAN HasFlowControl
;
1555 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1556 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1558 if (RemainingDevicePath
!= NULL
) {
1559 if (!IsDevicePathEnd (RemainingDevicePath
)) {
1560 Status
= EFI_UNSUPPORTED
;
1561 UartNode
= (UART_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
1562 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
1563 UartNode
->Header
.SubType
!= MSG_UART_DP
||
1564 sizeof (UART_DEVICE_PATH
) != DevicePathNodeLength ((EFI_DEVICE_PATH
*) UartNode
)) {
1567 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (UartNode
);
1568 if ((ReadUnaligned32 (&FlowControlNode
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
1575 // Check if USB I/O Protocol is attached on the controller handle.
1577 Status
= gBS
->OpenProtocol (
1579 &gEfiUsbIoProtocolGuid
,
1581 This
->DriverBindingHandle
,
1583 EFI_OPEN_PROTOCOL_BY_DRIVER
1585 if (Status
== EFI_ALREADY_STARTED
) {
1586 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
1589 Status
= gBS
->OpenProtocolInformation (
1591 &gEfiUsbIoProtocolGuid
,
1595 if (EFI_ERROR (Status
)) {
1598 for (Index
= 0; Index
< EntryCount
; Index
++) {
1599 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1600 Status
= gBS
->OpenProtocol (
1601 OpenInfoBuffer
[Index
].ControllerHandle
,
1602 &gEfiDevicePathProtocolGuid
,
1603 (VOID
**) &DevicePath
,
1604 This
->DriverBindingHandle
,
1606 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1608 if (!EFI_ERROR (Status
)) {
1609 HasFlowControl
= ContainsFlowControl (RemainingDevicePath
);
1610 if (HasFlowControl
^ ContainsFlowControl (DevicePath
)) {
1611 Status
= EFI_UNSUPPORTED
;
1617 FreePool (OpenInfoBuffer
);
1621 if (EFI_ERROR (Status
)) {
1625 gBS
->CloseProtocol (
1627 &gEfiUsbIoProtocolGuid
,
1628 This
->DriverBindingHandle
,
1632 Status
= gBS
->OpenProtocol (
1634 &gEfiDevicePathProtocolGuid
,
1635 (VOID
**) &ParentDevicePath
,
1636 This
->DriverBindingHandle
,
1638 EFI_OPEN_PROTOCOL_BY_DRIVER
1640 if (Status
== EFI_ALREADY_STARTED
) {
1643 if (EFI_ERROR (Status
)) {
1648 // Use the USB I/O Protocol interface to check whether Controller is
1649 // a USB Serial device that can be managed by this driver.
1651 Status
= EFI_SUCCESS
;
1653 if (!IsUsbSerial (UsbIo
)) {
1654 Status
= EFI_UNSUPPORTED
;
1659 gBS
->CloseProtocol (
1661 &gEfiDevicePathProtocolGuid
,
1662 This
->DriverBindingHandle
,
1669 Starts the USB Serial device with this driver.
1671 This function produces initializes the USB Serial device and
1672 produces the Serial IO Protocol.
1674 @param This[in] The USB Serial driver binding instance.
1675 @param Controller[in] Handle of device to bind driver to.
1676 @param RemainingDevicePath[in] Optional parameter use to pick a specific
1677 child device to start.
1679 @retval EFI_SUCCESS The controller is controlled by the usb USB
1681 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
1682 @retval Other This controller cannot be started.
1687 UsbSerialDriverBindingStart (
1688 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1689 IN EFI_HANDLE Controller
,
1690 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1694 EFI_USB_IO_PROTOCOL
*UsbIo
;
1695 USB_SER_DEV
*UsbSerialDevice
;
1696 UINT8 EndpointNumber
;
1697 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
1701 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
1702 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
1704 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1705 UART_DEVICE_PATH
*Uart
;
1706 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
1708 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1710 UsbSerialDevice
= AllocateZeroPool (sizeof (USB_SER_DEV
));
1711 ASSERT (UsbSerialDevice
!= NULL
);
1714 // Get the Parent Device path
1716 Status
= gBS
->OpenProtocol (
1718 &gEfiDevicePathProtocolGuid
,
1719 (VOID
**) &ParentDevicePath
,
1720 This
->DriverBindingHandle
,
1722 EFI_OPEN_PROTOCOL_BY_DRIVER
1724 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
1729 // Open USB I/O Protocol
1731 Status
= gBS
->OpenProtocol (
1733 &gEfiUsbIoProtocolGuid
,
1735 This
->DriverBindingHandle
,
1737 EFI_OPEN_PROTOCOL_BY_DRIVER
1739 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
1743 if (Status
== EFI_ALREADY_STARTED
) {
1744 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
1745 FreePool (UsbSerialDevice
);
1750 // Check to see if a child handle exists
1752 Status
= gBS
->OpenProtocolInformation (
1754 &gEfiSerialIoProtocolGuid
,
1758 if (EFI_ERROR (Status
)) {
1762 Status
= EFI_ALREADY_STARTED
;
1763 for (Index
= 0; Index
< EntryCount
; Index
++) {
1764 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1765 Status
= gBS
->OpenProtocol (
1766 OpenInfoBuffer
[Index
].ControllerHandle
,
1767 &gEfiSerialIoProtocolGuid
,
1768 (VOID
**) &SerialIo
,
1769 This
->DriverBindingHandle
,
1771 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1773 if (EFI_ERROR (Status
)) {
1775 if (!EFI_ERROR (Status
)) {
1776 Uart
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
1777 Status
= SerialIo
->SetAttributes (
1780 SerialIo
->Mode
->ReceiveFifoDepth
,
1781 SerialIo
->Mode
->Timeout
,
1782 (EFI_PARITY_TYPE
) Uart
->Parity
,
1784 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
1786 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
1787 if (!EFI_ERROR (Status
) && IsUartFlowControlNode (FlowControl
)) {
1788 Status
= SerialIo
->GetControl (
1792 if (!EFI_ERROR (Status
)) {
1793 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
1794 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1796 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1799 // Clear bits that are not allowed to be passed to SetControl
1801 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
|
1802 EFI_SERIAL_DATA_TERMINAL_READY
|
1803 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
|
1804 EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1805 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
1806 Status
= SerialIo
->SetControl (SerialIo
, Control
);
1813 FreePool (OpenInfoBuffer
);
1817 if (RemainingDevicePath
!= NULL
) {
1818 if (IsDevicePathEnd (RemainingDevicePath
)) {
1823 UsbSerialDevice
->UsbIo
= UsbIo
;
1826 // Get interface & endpoint descriptor
1828 UsbIo
->UsbGetInterfaceDescriptor (
1830 &UsbSerialDevice
->InterfaceDescriptor
1833 EndpointNumber
= UsbSerialDevice
->InterfaceDescriptor
.NumEndpoints
;
1836 // Traverse endpoints to find the IN and OUT endpoints that will send and
1841 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
1843 Status
= UsbIo
->UsbGetEndpointDescriptor (
1848 if (EFI_ERROR (Status
)) {
1852 if (EndpointDescriptor
.EndpointAddress
== FTDI_ENDPOINT_ADDRESS_OUT
) {
1854 // Set the Out endpoint device
1857 &UsbSerialDevice
->OutEndpointDescriptor
,
1858 &EndpointDescriptor
,
1859 sizeof(EndpointDescriptor
)
1864 if (EndpointDescriptor
.EndpointAddress
== FTDI_ENDPOINT_ADDRESS_IN
) {
1866 // Set the In endpoint device
1869 &UsbSerialDevice
->InEndpointDescriptor
,
1870 &EndpointDescriptor
,
1871 sizeof(EndpointDescriptor
)
1877 if (!FoundIn
|| !FoundOut
) {
1879 // No interrupt endpoint found, then return unsupported.
1881 Status
= EFI_UNSUPPORTED
;
1885 // set the initial values of UsbSerialDevice->LastSettings to the default
1888 UsbSerialDevice
->LastSettings
.BaudRate
= 115200;
1889 UsbSerialDevice
->LastSettings
.DataBits
= 8;
1890 UsbSerialDevice
->LastSettings
.Parity
= NoParity
;
1891 UsbSerialDevice
->LastSettings
.ReceiveFifoDepth
= FTDI_MAX_RECEIVE_FIFO_DEPTH
;
1892 UsbSerialDevice
->LastSettings
.StopBits
= OneStopBit
;
1893 UsbSerialDevice
->LastSettings
.Timeout
= FTDI_TIMEOUT
;
1896 // set the initial values of UsbSerialDevice->ControlValues
1898 UsbSerialDevice
->ControlValues
.DtrState
= FALSE
;
1899 UsbSerialDevice
->ControlValues
.RtsState
= FALSE
;
1900 UsbSerialDevice
->ControlValues
.HardwareFlowControl
= FALSE
;
1901 UsbSerialDevice
->ControlValues
.HardwareLoopBack
= FALSE
;
1902 UsbSerialDevice
->ControlValues
.SoftwareLoopBack
= FALSE
;
1905 // set the values of UsbSerialDevice->UartDevicePath
1907 UsbSerialDevice
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1908 UsbSerialDevice
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
1909 UsbSerialDevice
->UartDevicePath
.Header
.Length
[0] = (UINT8
) (sizeof (UART_DEVICE_PATH
));
1910 UsbSerialDevice
->UartDevicePath
.Header
.Length
[1] = (UINT8
) ((sizeof (UART_DEVICE_PATH
)) >> 8);
1913 // set the values of UsbSerialDevice->FlowControlDevicePath
1914 UsbSerialDevice
->FlowControlDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1915 UsbSerialDevice
->FlowControlDevicePath
.Header
.SubType
= MSG_VENDOR_DP
;
1916 UsbSerialDevice
->FlowControlDevicePath
.Header
.Length
[0] = (UINT8
) (sizeof (UART_FLOW_CONTROL_DEVICE_PATH
));
1917 UsbSerialDevice
->FlowControlDevicePath
.Header
.Length
[1] = (UINT8
) ((sizeof (UART_FLOW_CONTROL_DEVICE_PATH
)) >> 8);
1918 UsbSerialDevice
->FlowControlDevicePath
.FlowControlMap
= 0;
1920 Status
= SetAttributesInternal (
1922 UsbSerialDevice
->LastSettings
.BaudRate
,
1923 UsbSerialDevice
->LastSettings
.ReceiveFifoDepth
,
1924 UsbSerialDevice
->LastSettings
.Timeout
,
1925 UsbSerialDevice
->LastSettings
.Parity
,
1926 UsbSerialDevice
->LastSettings
.DataBits
,
1927 UsbSerialDevice
->LastSettings
.StopBits
1930 ASSERT_EFI_ERROR (Status
);
1932 Status
= SetControlBitsInternal (
1934 &(UsbSerialDevice
->ControlValues
)
1937 ASSERT_EFI_ERROR (Status
);
1940 // Publish Serial GUID and protocol
1943 UsbSerialDevice
->Signature
= USB_SER_DEV_SIGNATURE
;
1944 UsbSerialDevice
->SerialIo
.Reset
= SerialReset
;
1945 UsbSerialDevice
->SerialIo
.SetControl
= SetControlBits
;
1946 UsbSerialDevice
->SerialIo
.SetAttributes
= SetAttributes
;
1947 UsbSerialDevice
->SerialIo
.GetControl
= GetControlBits
;
1948 UsbSerialDevice
->SerialIo
.Read
= ReadSerialIo
;
1949 UsbSerialDevice
->SerialIo
.Write
= WriteSerialIo
;
1952 // Set the static Serial IO modes that will display when running
1953 // "sermode" within the UEFI shell.
1956 UsbSerialDevice
->SerialIo
.Mode
->Timeout
= 0;
1957 UsbSerialDevice
->SerialIo
.Mode
->BaudRate
= 115200;
1958 UsbSerialDevice
->SerialIo
.Mode
->DataBits
= 8;
1959 UsbSerialDevice
->SerialIo
.Mode
->Parity
= 1;
1960 UsbSerialDevice
->SerialIo
.Mode
->StopBits
= 1;
1962 UsbSerialDevice
->ParentDevicePath
= ParentDevicePath
;
1963 UsbSerialDevice
->ControllerHandle
= NULL
;
1967 // Allocate space for the receive buffer
1969 UsbSerialDevice
->DataBuffer
= AllocateZeroPool (SW_FIFO_DEPTH
);
1972 // Initialize data buffer pointers.
1973 // Head==Tail = true means buffer is empty.
1975 UsbSerialDevice
->DataBufferHead
= 0;
1976 UsbSerialDevice
->DataBufferTail
= 0;
1978 UsbSerialDevice
->ControllerNameTable
= NULL
;
1981 gUsbSerialComponentName
.SupportedLanguages
,
1982 &UsbSerialDevice
->ControllerNameTable
,
1983 L
"FTDI USB Serial Adapter",
1988 gUsbSerialComponentName2
.SupportedLanguages
,
1989 &UsbSerialDevice
->ControllerNameTable
,
1990 L
"FTDI USB Serial Adapter",
1994 Status
= SetInitialStatus (UsbSerialDevice
);
1995 ASSERT_EFI_ERROR (Status
);
1998 // Create a polling loop to check for input
2002 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
2004 UsbSerialDriverCheckInput
,
2006 &(UsbSerialDevice
->PollingLoop
)
2009 // add code to set trigger time based on baud rate
2010 // setting to 0.5s for now
2013 UsbSerialDevice
->PollingLoop
,
2015 EFI_TIMER_PERIOD_MILLISECONDS (500)
2019 // Check if the remaining device path is null. If it is not null change the settings
2020 // of the device to match those on the device path
2022 if (RemainingDevicePath
!= NULL
) {
2024 &UsbSerialDevice
->UartDevicePath
,
2025 RemainingDevicePath
,
2026 sizeof (UART_DEVICE_PATH
)
2028 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
2029 if (IsUartFlowControlNode (FlowControl
)) {
2030 UsbSerialDevice
->FlowControlDevicePath
.FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
2037 // Build the device path by appending the UART node to the parent device path
2039 UsbSerialDevice
->DevicePath
= AppendDevicePathNode (
2041 (EFI_DEVICE_PATH_PROTOCOL
*) &UsbSerialDevice
->UartDevicePath
2044 // Continue building the device path by appending the flow control node
2046 TempDevicePath
= UsbSerialDevice
->DevicePath
;
2047 UsbSerialDevice
->DevicePath
= AppendDevicePathNode (
2049 (EFI_DEVICE_PATH_PROTOCOL
*) &UsbSerialDevice
->FlowControlDevicePath
2051 FreePool (TempDevicePath
);
2053 if (UsbSerialDevice
->DevicePath
== NULL
) {
2054 Status
= EFI_OUT_OF_RESOURCES
;
2059 // Install protocol interfaces for the device
2061 Status
= gBS
->InstallMultipleProtocolInterfaces (
2062 &UsbSerialDevice
->ControllerHandle
,
2063 &gEfiDevicePathProtocolGuid
,
2064 UsbSerialDevice
->DevicePath
,
2065 &gEfiSerialIoProtocolGuid
,
2066 &UsbSerialDevice
->SerialIo
,
2069 if (EFI_ERROR (Status
)){
2074 // Open for child device
2076 Status
= gBS
->OpenProtocol (
2078 &gEfiUsbIoProtocolGuid
,
2080 This
->DriverBindingHandle
,
2081 UsbSerialDevice
->ControllerHandle
,
2082 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
2085 UsbSerialDevice
->Shutdown
= FALSE
;
2094 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2096 &gEfiSerialIoProtocolGuid
,
2097 &UsbSerialDevice
->SerialIo
,
2100 if (EFI_ERROR (Status
)) {
2104 FreePool (UsbSerialDevice
->DataBuffer
);
2105 FreePool (UsbSerialDevice
);
2107 UsbSerialDevice
= NULL
;
2108 gBS
->CloseProtocol (
2110 &gEfiUsbIoProtocolGuid
,
2111 This
->DriverBindingHandle
,
2120 Stop the USB Serial device handled by this driver.
2122 @param This[in] The USB Serial driver binding protocol.
2123 @param Controller[in] The controller to release.
2124 @param NumberOfChildren[in] The number of handles in ChildHandleBuffer.
2125 @param ChildHandleBuffer[in] The array of child handle.
2127 @retval EFI_SUCCESS The device was stopped.
2128 @retval EFI_UNSUPPORTED Serial IO Protocol is not installed on
2130 @retval EFI_DEVICE_ERROR The device could not be stopped due to a
2132 @retval Others Fail to uninstall protocols attached on the
2138 UsbSerialDriverBindingStop (
2139 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2140 IN EFI_HANDLE Controller
,
2141 IN UINTN NumberOfChildren
,
2142 IN EFI_HANDLE
*ChildHandleBuffer
2146 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
2147 EFI_USB_IO_PROTOCOL
*UsbIo
;
2148 USB_SER_DEV
*UsbSerialDevice
;
2150 BOOLEAN AllChildrenStopped
;
2152 Status
= EFI_SUCCESS
;
2153 UsbSerialDevice
= NULL
;
2155 if (NumberOfChildren
== 0) {
2159 Status
= gBS
->CloseProtocol (
2161 &gEfiUsbIoProtocolGuid
,
2162 This
->DriverBindingHandle
,
2165 Status
= gBS
->CloseProtocol (
2167 &gEfiDevicePathProtocolGuid
,
2168 This
->DriverBindingHandle
,
2174 AllChildrenStopped
= TRUE
;
2176 for (Index
= 0; Index
< NumberOfChildren
;Index
++) {
2177 Status
= gBS
->OpenProtocol (
2178 ChildHandleBuffer
[Index
],
2179 &gEfiSerialIoProtocolGuid
,
2180 (VOID
**) &SerialIo
,
2181 This
->DriverBindingHandle
,
2183 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2185 if (Status
== EFI_SUCCESS
) {//!EFI_ERROR (Status)) {
2186 UsbSerialDevice
= USB_SER_DEV_FROM_THIS (SerialIo
);
2187 Status
= gBS
->CloseProtocol (
2189 &gEfiUsbIoProtocolGuid
,
2190 This
->DriverBindingHandle
,
2191 ChildHandleBuffer
[Index
]
2193 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2194 ChildHandleBuffer
[Index
],
2195 &gEfiDevicePathProtocolGuid
,
2196 UsbSerialDevice
->DevicePath
,
2197 &gEfiSerialIoProtocolGuid
,
2198 &UsbSerialDevice
->SerialIo
,
2202 if (EFI_ERROR (Status
)) {
2205 &gEfiUsbIoProtocolGuid
,
2207 This
->DriverBindingHandle
,
2208 ChildHandleBuffer
[Index
],
2209 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
2212 if (UsbSerialDevice
->DevicePath
!= NULL
) {
2213 gBS
->FreePool (UsbSerialDevice
->DevicePath
);
2216 UsbSerialDevice
->PollingLoop
,
2220 gBS
->CloseEvent (UsbSerialDevice
->PollingLoop
);
2221 UsbSerialDevice
->Shutdown
= TRUE
;
2222 FreeUnicodeStringTable (UsbSerialDevice
->ControllerNameTable
);
2223 FreePool (UsbSerialDevice
->DataBuffer
);
2224 FreePool (UsbSerialDevice
);
2227 if (EFI_ERROR (Status
)) {
2228 AllChildrenStopped
= FALSE
;
2232 if (!AllChildrenStopped
) {
2233 return EFI_DEVICE_ERROR
;
2239 // Serial IO Member Functions
2243 Reset the serial device.
2245 @param This[in] Protocol instance pointer.
2247 @retval EFI_SUCCESS The device was reset.
2248 @retval EFI_DEVICE_ERROR The serial device could not be reset.
2254 IN EFI_SERIAL_IO_PROTOCOL
*This
2258 USB_SER_DEV
*UsbSerialDevice
;
2260 UsbSerialDevice
= USB_SER_DEV_FROM_THIS (This
);
2261 Status
= ResetInternal (UsbSerialDevice
);
2262 if (EFI_ERROR (Status
)){
2263 return EFI_DEVICE_ERROR
;
2269 Set the control bits on a serial device.
2271 @param This[in] Protocol instance pointer.
2272 @param Control[in] Set the bits of Control that are settable.
2274 @retval EFI_SUCCESS The new control bits were set on the serial device.
2275 @retval EFI_UNSUPPORTED The serial device does not support this operation.
2276 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
2282 IN EFI_SERIAL_IO_PROTOCOL
*This
,
2287 USB_SER_DEV
*UsbSerialDevice
;
2288 CONTROL_BITS ControlBits
;
2290 UsbSerialDevice
= USB_SER_DEV_FROM_THIS (This
);
2293 // check for invalid control parameters
2295 if ((Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
|
2296 EFI_SERIAL_DATA_TERMINAL_READY
|
2297 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
|
2298 EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
2299 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) != 0 ) {
2300 return EFI_UNSUPPORTED
;
2304 // check the control parameters and set the correct setting for
2305 // the paramerts of ControlBits
2306 // both loopback enables are always set to FALSE
2308 ControlBits
.HardwareLoopBack
= FALSE
;
2309 ControlBits
.SoftwareLoopBack
= FALSE
;
2311 // check for hardware flow control
2313 if ((Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
2314 ControlBits
.HardwareFlowControl
= TRUE
;
2316 ControlBits
.HardwareFlowControl
= FALSE
;
2319 // check for DTR enabled
2321 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
2322 ControlBits
.DtrState
= TRUE
;
2324 ControlBits
.DtrState
= FALSE
;
2327 // check for RTS enabled
2329 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
2330 ControlBits
.RtsState
= TRUE
;
2332 ControlBits
.RtsState
= FALSE
;
2336 // set the control values with a call to SetControlBitsInternal()
2338 Status
= SetControlBitsInternal (UsbSerialDevice
, &ControlBits
);
2344 calls SetAttributesInternal() to set the baud rate, receive FIFO depth,
2345 transmit/receive time out, parity, data buts, and stop bits on a serial
2348 @param This[in] Protocol instance pointer.
2349 @param BaudRate[in] The requested baud rate. A BaudRate value of 0
2350 will use the device's default interface speed.
2351 @param ReveiveFifoDepth[in] The requested depth of the FIFO on the receive
2352 side of the serial interface. A ReceiveFifoDepth
2353 value of 0 will use the device's default FIFO
2355 @param Timeout[in] The requested time out for a single character in
2356 microseconds.This timeout applies to both the
2357 transmit and receive side of the interface. A
2358 Timeout value of 0 will use the device's default
2360 @param Parity[in] The type of parity to use on this serial device.
2361 A Parity value of DefaultParity will use the
2362 device's default parity value.
2363 @param DataBits[in] The number of data bits to use on the serial
2364 device. A DataBit vaule of 0 will use the
2365 device's default data bit setting.
2366 @param StopBits[in] The number of stop bits to use on this serial
2367 device. A StopBits value of DefaultStopBits will
2368 use the device's default number of stop bits.
2370 @retval EFI_SUCCESS The attributes were set
2371 @retval EFI_DEVICE_ERROR The attributes were not able to be
2377 IN EFI_SERIAL_IO_PROTOCOL
*This
,
2379 IN UINT32 ReceiveFifoDepth
,
2381 IN EFI_PARITY_TYPE Parity
,
2383 IN EFI_STOP_BITS_TYPE StopBits
2388 USB_SER_DEV
*UsbSerialDevice
;
2390 UsbSerialDevice
= USB_SER_DEV_FROM_THIS (This
);
2392 Status
= SetAttributesInternal (
2401 if (EFI_ERROR (Status
)) {
2410 Retrieves the status of the control bits on a serial device.
2412 @param This[in] Protocol instance pointer.
2413 @param Control[out] A pointer to return the current Control signals
2414 from the serial device.
2416 @retval EFI_SUCCESS The control bits were read from the serial
2418 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
2424 IN EFI_SERIAL_IO_PROTOCOL
*This
,
2428 USB_SER_DEV
*UsbSerialDevice
;
2431 UsbSerialDevice
= USB_SER_DEV_FROM_THIS (This
);
2435 Status
= GetControlBitsInternal (UsbSerialDevice
, Control
);
2437 if (EFI_ERROR (Status
)) {
2438 return EFI_DEVICE_ERROR
;
2444 Reads data from a serial device.
2446 @param This[in] Protocol instance pointer.
2447 @param BufferSize[in, out] On input, the size of the Buffer. On output,
2448 the amount of data returned in Buffer.
2449 @param Buffer[out] The buffer to return the data into.
2451 @retval EFI_SUCCESS The data was read.
2452 @retval EFI_DEVICE_ERROR The device reported an error.
2453 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
2459 IN EFI_SERIAL_IO_PROTOCOL
*This
,
2460 IN OUT UINTN
*BufferSize
,
2465 UINTN RemainingCallerBufferSize
;
2466 USB_SER_DEV
*UsbSerialDevice
;
2470 if (*BufferSize
== 0) {
2474 if (Buffer
== NULL
) {
2475 return EFI_DEVICE_ERROR
;
2478 Status
= EFI_SUCCESS
;
2479 UsbSerialDevice
= USB_SER_DEV_FROM_THIS (This
);
2482 // Clear out any data that we already have in our internal buffer
2484 for (Index
= 0; Index
< *BufferSize
; Index
++) {
2485 if (UsbSerialDevice
->DataBufferHead
== UsbSerialDevice
->DataBufferTail
) {
2490 // Still have characters in the buffer to return
2492 ((UINT8
*)Buffer
)[Index
] = UsbSerialDevice
->DataBuffer
[UsbSerialDevice
->DataBufferHead
];
2493 UsbSerialDevice
->DataBufferHead
= (UsbSerialDevice
->DataBufferHead
+ 1) % SW_FIFO_DEPTH
;
2497 // If we haven't filled the caller's buffer using data that we already had on
2498 // hand We need to generate an additional USB request to try and fill the
2501 if (Index
!= *BufferSize
) {
2502 RemainingCallerBufferSize
= *BufferSize
- Index
;
2503 Status
= ReadDataFromUsb (
2505 &RemainingCallerBufferSize
,
2506 (VOID
*)(((CHAR8
*)Buffer
) + Index
)
2508 if (!EFI_ERROR (Status
)) {
2509 *BufferSize
= RemainingCallerBufferSize
+ Index
;
2511 *BufferSize
= Index
;
2515 if (UsbSerialDevice
->DataBufferHead
== UsbSerialDevice
->DataBufferTail
) {
2517 // Data buffer has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY flag
2519 UsbSerialDevice
->ControlBits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
2522 // There is some leftover data, clear EFI_SERIAL_INPUT_BUFFER_EMPTY flag
2524 UsbSerialDevice
->ControlBits
&= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY
);
2530 Writes data to a serial device.
2532 @param This[in] Protocol instance pointer.
2533 @param BufferSize[in, out] On input, the size of the Buffer. On output,
2534 the amount of data actually written.
2535 @param Buffer[in] The buffer of data to write
2537 @retval EFI_SUCCESS The data was written.
2538 @retval EFI_DEVICE_ERROR The device reported an error.
2539 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
2545 IN EFI_SERIAL_IO_PROTOCOL
*This
,
2546 IN OUT UINTN
*BufferSize
,
2551 USB_SER_DEV
*UsbSerialDevice
;
2554 UsbSerialDevice
= USB_SER_DEV_FROM_THIS (This
);
2556 if (UsbSerialDevice
->Shutdown
) {
2557 return EFI_DEVICE_ERROR
;
2560 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2562 Status
= UsbSerialDataTransfer (
2570 gBS
->RestoreTPL (Tpl
);
2571 if (EFI_ERROR (Status
)) {
2572 if (Status
== EFI_TIMEOUT
){
2575 return EFI_DEVICE_ERROR
;