1 /** @file
2   USB Serial Driver that manages USB to Serial and produces Serial IO Protocol.
3 
4 Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
5 Portions Copyright 2012 Ashley DeSimone
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 //
11 
12 // Tested with VEND_ID 0x0403, DEVICE_ID 0x6001
13 //
14 // Driver starts the device with the following values:
15 // 115200, No parity, 8 data bits, 1 stop bit, No Flow control
16 //
17 
18 #include "FtdiUsbSerialDriver.h"
19 
20 //
21 // Table of supported devices. This is the device information that this
22 // driver was developed with. Add other FTDI devices as needed.
23 //
24 USB_DEVICE gUSBDeviceList[] = {
25   {VID_FTDI, DID_FTDI_FT232},
26   {0,0}
27 };
28 
29 //
30 // USB Serial Driver Global Variables
31 //
32 EFI_DRIVER_BINDING_PROTOCOL  gUsbSerialDriverBinding = {
33   UsbSerialDriverBindingSupported,
34   UsbSerialDriverBindingStart,
35   UsbSerialDriverBindingStop,
36   0xa,
37   NULL,
38   NULL
39 };
40 
41 //
42 // Table with the nearest power of 2 for the numbers 0-15
43 //
44 UINT8 gRoundedPowersOf2[16] = { 0, 2, 2, 4, 4, 4, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16 };
45 
46 /**
47   Check to see if the device path node is the Flow control node
48 
49   @param[in] FlowControl    The device path node to be checked
50 
51   @retval    TRUE           It is the flow control node
52   @retval    FALSE          It is not the flow control node
53 
54 **/
55 BOOLEAN
IsUartFlowControlNode(IN UART_FLOW_CONTROL_DEVICE_PATH * FlowControl)56 IsUartFlowControlNode (
57   IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
58   )
59 {
60   return (BOOLEAN) (
61            (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
62            (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
63            (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
64            );
65 }
66 
67 /**
68   Checks the device path to see if it contains flow control.
69 
70   @param[in] DevicePath    The device path to be checked
71 
72   @retval    TRUE          It contains flow control
73   @retval    FALSE         It does not contain flow control
74 
75 **/
76 BOOLEAN
ContainsFlowControl(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)77 ContainsFlowControl (
78   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath
79   )
80 {
81   while (!IsDevicePathEnd (DevicePath)) {
82     if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
83       return TRUE;
84     }
85     DevicePath = NextDevicePathNode (DevicePath);
86   }
87   return FALSE;
88 }
89 
90 /**
91   Transfer the data between the device and host.
92 
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.
96 
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
102 
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
107 
108 **/
109 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)110 UsbSerialDataTransfer (
111   IN USB_SER_DEV             *UsbBot,
112   IN EFI_USB_DATA_DIRECTION  DataDir,
113   IN OUT VOID                *Data,
114   IN OUT UINTN               *TransLen,
115   IN UINT32                  Timeout
116   )
117 {
118   EFI_USB_ENDPOINT_DESCRIPTOR  *Endpoint;
119   EFI_STATUS                   Status;
120   UINT32                       Result;
121 
122   //
123   // If no data to transfer, just return EFI_SUCCESS.
124   //
125   if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
126     return EFI_SUCCESS;
127   }
128 
129   //
130   // Select the endpoint then issue the transfer
131   //
132   if (DataDir == EfiUsbDataIn) {
133     Endpoint = &UsbBot->InEndpointDescriptor;
134   } else {
135     Endpoint = &UsbBot->OutEndpointDescriptor;
136   }
137 
138   Result = 0;
139   Status = UsbBot->UsbIo->UsbBulkTransfer (
140                             UsbBot->UsbIo,
141                             Endpoint->EndpointAddress,
142                             Data,
143                             TransLen,
144                             Timeout,
145                             &Result
146                             );
147   if (EFI_ERROR (Status)) {
148     if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {
149       Status = EFI_NOT_READY;
150     } else {
151       UsbBot->Shutdown = TRUE; // Fixes infinite loop in older EFI
152     }
153     return Status;
154   }
155   return Status;
156 }
157 
158 /**
159   Sets the status values of the Usb Serial Device.
160 
161   @param  UsbSerialDevice[in]  Handle to the Usb Serial Device to set the status
162                                for
163   @param  StatusBuffer[in]     Buffer holding the status values
164 
165   @retval EFI_SUCCESS          The status values were read and set correctly
166 
167 **/
168 EFI_STATUS
169 EFIAPI
SetStatusInternal(IN USB_SER_DEV * UsbSerialDevice,IN UINT8 * StatusBuffer)170 SetStatusInternal (
171   IN USB_SER_DEV  *UsbSerialDevice,
172   IN UINT8        *StatusBuffer
173   )
174 {
175   UINT8  Msr;
176 
177   Msr = (StatusBuffer[0] & MSR_MASK);
178 
179   //
180   // set the Status values to disabled
181   //
182   UsbSerialDevice->StatusValues.CtsState = FALSE;
183   UsbSerialDevice->StatusValues.DsrState = FALSE;
184   UsbSerialDevice->StatusValues.RiState  = FALSE;
185   UsbSerialDevice->StatusValues.SdState  = FALSE;
186 
187   //
188   // Check the values from the status buffer and set the appropriate status
189   // values to enabled
190   //
191   if ((Msr & CTS_MASK) == CTS_MASK) {
192     UsbSerialDevice->StatusValues.CtsState = TRUE;
193   }
194   if ((Msr & DSR_MASK) == DSR_MASK) {
195     UsbSerialDevice->StatusValues.DsrState = TRUE;
196   }
197   if ((Msr & RI_MASK) == RI_MASK) {
198     UsbSerialDevice->StatusValues.RiState = TRUE;
199   }
200   if ((Msr & SD_MASK) == SD_MASK) {
201     UsbSerialDevice->StatusValues.SdState = TRUE;
202   }
203   return EFI_SUCCESS;
204 }
205 
206 /**
207   Initiates a read operation on the Usb Serial Device.
208 
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
214                                      buffer.
215   @param  Buffer [out]               The buffer to return the data into.
216 
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.
220 
221 **/
222 EFI_STATUS
223 EFIAPI
ReadDataFromUsb(IN USB_SER_DEV * UsbSerialDevice,IN OUT UINTN * BufferSize,OUT VOID * Buffer)224 ReadDataFromUsb (
225   IN USB_SER_DEV  *UsbSerialDevice,
226   IN OUT UINTN    *BufferSize,
227   OUT VOID        *Buffer
228   )
229 {
230   EFI_STATUS  Status;
231   UINTN       ReadBufferSize;
232   UINT8       *ReadBuffer;
233   UINTN       Index;
234   EFI_TPL     Tpl;
235   UINT8       StatusBuffer[2]; // buffer to store the status bytes
236 
237   ReadBufferSize = 512;
238   ReadBuffer     = &(UsbSerialDevice->ReadBuffer[0]);
239 
240   if (UsbSerialDevice->Shutdown) {
241     return EFI_DEVICE_ERROR;
242   }
243 
244   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
245 
246   Status = UsbSerialDataTransfer (
247              UsbSerialDevice,
248              EfiUsbDataIn,
249              ReadBuffer,
250              &ReadBufferSize,
251              FTDI_TIMEOUT*2  //Padded because timers won't be exactly aligned
252              );
253   if (EFI_ERROR (Status)) {
254     gBS->RestoreTPL (Tpl);
255     if (Status == EFI_TIMEOUT) {
256       return EFI_TIMEOUT;
257     } else {
258       return EFI_DEVICE_ERROR;
259     }
260   }
261 
262   //
263   // Store the status bytes in the status buffer
264   //
265   for (Index = 0; Index < 2; Index++) {//only the first 2 bytes are status bytes
266     StatusBuffer[Index] = ReadBuffer[Index];
267   }
268   //
269   // update the statusvalue field of the usbserialdevice
270   //
271   Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);
272   if (Status != EFI_SUCCESS) {
273   }
274 
275   //
276   // Store the read data in the read buffer, start at 2 to ignore status bytes
277   //
278   for (Index = 2; Index < ReadBufferSize; Index++) {
279     if (((UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH) == UsbSerialDevice->DataBufferHead) {
280       break;
281     }
282     if (ReadBuffer[Index] == 0x00) {
283       //
284       // This is null, do not add
285       //
286     } else {
287       UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferTail] = ReadBuffer[Index];
288       UsbSerialDevice->DataBufferTail = (UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH;
289     }
290   }
291 
292   //
293   // Read characters out of the buffer to satisfy caller's request.
294   //
295   for (Index = 0; Index < *BufferSize; Index++) {
296     if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
297       break;
298     }
299     //
300     // Still have characters in the buffer to return
301     //
302     ((UINT8 *)Buffer)[Index]        = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];
303     UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;
304   }
305   //
306   // Return actual number of bytes returned.
307   //
308   *BufferSize = Index;
309   gBS->RestoreTPL (Tpl);
310   return EFI_SUCCESS;
311 }
312 
313 /**
314   Sets the initial status values of the Usb Serial Device by reading the status
315   bytes from the device.
316 
317   @param  UsbSerialDevice[in]  Handle to the Usb Serial Device that needs its
318                                initial status values set
319 
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
323                                timeout
324   @retval EFI_DEVICE_ERROR     The device reported an error during the read of
325                                the status bytes
326 
327 **/
328 EFI_STATUS
329 EFIAPI
SetInitialStatus(IN USB_SER_DEV * UsbSerialDevice)330 SetInitialStatus (
331   IN USB_SER_DEV          *UsbSerialDevice
332   )
333 {
334   EFI_STATUS      Status;
335   UINTN           BufferSize;
336   EFI_TPL         Tpl;
337   UINT8           StatusBuffer[2];
338 
339   Status          = EFI_UNSUPPORTED;
340   BufferSize      = sizeof (StatusBuffer);
341 
342   if (UsbSerialDevice->Shutdown) {
343     return EFI_DEVICE_ERROR;
344   }
345 
346   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
347 
348   Status = UsbSerialDataTransfer (
349              UsbSerialDevice,
350              EfiUsbDataIn,
351              StatusBuffer,
352              &BufferSize,
353              40    //Slightly more than 2x the FTDI polling frequency to make sure that data will be returned
354              );
355 
356   Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);
357 
358   gBS->RestoreTPL (Tpl);
359 
360   return Status;
361 }
362 
363 /**
364   UsbSerialDriverCheckInput.
365   attempts to read data in from the device periodically, stores any read data
366   and updates the control attributes.
367 
368   @param  Event[in]
369   @param  Context[in]....The current instance of the USB serial device
370 
371 **/
372 VOID
373 EFIAPI
UsbSerialDriverCheckInput(IN EFI_EVENT Event,IN VOID * Context)374 UsbSerialDriverCheckInput (
375   IN  EFI_EVENT  Event,
376   IN  VOID       *Context
377   )
378 {
379   UINTN        BufferSize;
380   USB_SER_DEV  *UsbSerialDevice;
381 
382   UsbSerialDevice = (USB_SER_DEV*)Context;
383 
384   if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
385     //
386     // Data buffer is empty, try to read from device
387     //
388     BufferSize = 0;
389     ReadDataFromUsb (UsbSerialDevice, &BufferSize, NULL);
390     if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
391       //
392       // Data buffer still has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY
393       // flag
394       //
395       UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
396     } else {
397       //
398       // Read has returned some data, clear the EFI_SERIAL_INPUT_BUFFER_EMPTY
399       // flag
400       //
401       UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
402     }
403   } else {
404     //
405     // Data buffer has data, no read attempt required
406     //
407     UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
408   }
409 }
410 
411 /**
412   Encodes the baud rate into the format expected by the Ftdi device.
413 
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
417 
418   @return EFI_SUCCESS                 Baudrate encoding was calculated
419                                       successfully
420   @return EFI_INVALID_PARAMETER       An invalid value of BaudRate was received
421 
422 **/
423 EFI_STATUS
424 EFIAPI
EncodeBaudRateForFtdi(IN UINT64 BaudRate,OUT UINT16 * EncodedBaudRate)425 EncodeBaudRateForFtdi (
426   IN  UINT64  BaudRate,
427   OUT UINT16  *EncodedBaudRate
428   )
429 {
430   UINT32 Divisor;
431   UINT32 AdjustedFrequency;
432   UINT16 Result;
433 
434   //
435   // Check to make sure we won't get an integer overflow
436   //
437   if ((BaudRate < 178) || ( BaudRate > ((FTDI_UART_FREQUENCY * 100) / 97))) {
438     return EFI_INVALID_PARAMETER;
439   }
440 
441   //
442   // Baud Rates of 2000000 and 3000000 are special cases
443   //
444   if ((BaudRate >= FTDI_SPECIAL_CASE_300_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_300_MAX)) {
445     *EncodedBaudRate = 0;
446     return EFI_SUCCESS;
447   }
448   if ((BaudRate >= FTDI_SPECIAL_CASE_200_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_200_MAX)) {
449     *EncodedBaudRate = 1;
450     return EFI_SUCCESS;
451   }
452 
453   //
454   // Compute divisor
455   //
456   Divisor = (FTDI_UART_FREQUENCY << 4) / (UINT32)BaudRate;
457 
458   //
459   // Round the last 4 bits to the nearest power of 2
460   //
461   Divisor = (Divisor & ~(0xF)) + (gRoundedPowersOf2[Divisor & 0xF]);
462 
463   //
464   // Check to make sure computed divisor is within
465   // the min and max that FTDI controller will accept
466   //
467   if (Divisor < FTDI_MIN_DIVISOR) {
468     Divisor = FTDI_MIN_DIVISOR;
469   } else if (Divisor > FTDI_MAX_DIVISOR) {
470     Divisor = FTDI_MAX_DIVISOR;
471   }
472 
473   //
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.
477   //
478   // (3MHz * 1600) / 103 = 46601941
479   // (3MHz * 1600) / 97  = 49484536
480   //
481   AdjustedFrequency = (((UINT32)BaudRate) * Divisor);
482   if ((AdjustedFrequency < FTDI_MIN_FREQUENCY) || (AdjustedFrequency > FTDI_MAX_FREQUENCY)) {
483     return EFI_INVALID_PARAMETER;
484   }
485 
486   //
487   // Encode the Divisor into the format FTDI expects
488   //
489   Result = (UINT16)(Divisor >> 4);
490   if ((Divisor & 0x8) != 0) {
491     Result |= 0x4000;
492   } else if ((Divisor & 0x4) != 0) {
493     Result |= 0x8000;
494   } else if ((Divisor & 0x2) != 0) {
495     Result |= 0xC000;
496   }
497 
498   *EncodedBaudRate = Result;
499   return EFI_SUCCESS;
500 }
501 
502 /**
503   Uses USB I/O to check whether the device is a USB Serial device.
504 
505   @param  UsbIo[in]    Pointer to a USB I/O protocol instance.
506 
507   @retval TRUE         Device is a USB Serial device.
508   @retval FALSE        Device is a not USB Serial device.
509 
510 **/
511 BOOLEAN
IsUsbSerial(IN EFI_USB_IO_PROTOCOL * UsbIo)512 IsUsbSerial (
513   IN  EFI_USB_IO_PROTOCOL  *UsbIo
514   )
515 {
516   EFI_STATUS                 Status;
517   EFI_USB_DEVICE_DESCRIPTOR  DeviceDescriptor;
518   CHAR16                     *StrMfg;
519   BOOLEAN                    Found;
520   UINT32                     Index;
521 
522   //
523   // Get the default device descriptor
524   //
525   Status = UsbIo->UsbGetDeviceDescriptor (
526                     UsbIo,
527                     &DeviceDescriptor
528                     );
529   if (EFI_ERROR (Status)) {
530     return FALSE;
531   }
532 
533   Found = FALSE;
534   Index = 0;
535   while (gUSBDeviceList[Index].VendorId != 0 &&
536          gUSBDeviceList[Index].DeviceId != 0 &&
537          !Found                                  ) {
538     if (DeviceDescriptor.IdProduct == gUSBDeviceList[Index].DeviceId &&
539         DeviceDescriptor.IdVendor  == gUSBDeviceList[Index].VendorId      ){
540         //
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
544         //
545         StrMfg = NULL;
546         Status = UsbIo->UsbGetStringDescriptor (
547                           UsbIo,
548                           USB_US_LANG_ID, // LANGID selector, should make this
549                                           // more robust to verify lang support
550                                           // for device
551                           DeviceDescriptor.StrManufacturer,
552                           &StrMfg
553                           );
554         if (StrMfg != NULL) {
555           FreePool (StrMfg);
556         }
557         if (EFI_ERROR (Status)) {
558           return FALSE;
559         }
560         return TRUE;
561     }
562     Index++;
563   }
564   return FALSE;
565 }
566 
567 /**
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.
570 
571   @param  UsbIo[in]                  Usb Io Protocol instance pointer
572   @param  DataBits[in]               The data bits value to be set on the Usb
573                                      Serial Device
574   @param  Parity[in]                 The parity type that will be set on the Usb
575                                      Serial Device
576   @param  StopBits[in]               The stop bits type that will be set on the
577                                      Usb Serial Device
578   @param  LastSettings[in]           A pointer to the Usb Serial Device's
579                                      PREVIOUS_ATTRIBUTES item
580 
581   @retval EFI_SUCCESS                The data items were correctly set on the
582                                      USB Serial Device
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
587 
588 **/
589 EFI_STATUS
590 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)591 SetDataInternal (
592   IN EFI_USB_IO_PROTOCOL  *UsbIo,
593   IN UINT8                DataBits,
594   IN EFI_PARITY_TYPE      Parity,
595   IN EFI_STOP_BITS_TYPE   StopBits,
596   IN PREVIOUS_ATTRIBUTES  *LastSettings
597   )
598 {
599   EFI_STATUS              Status;
600   EFI_USB_DEVICE_REQUEST  DevReq;
601   UINT32                  ReturnValue;
602   UINT8                   ConfigurationValue;
603 
604   //
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
607   //
608   if ((DataBits == 0) && (StopBits == OneFiveStopBits)) {
609     if ((LastSettings->DataBits == 6) || (LastSettings->DataBits == 7) || (LastSettings->DataBits == 8)) {
610       return EFI_INVALID_PARAMETER;
611     }
612   } else if ((StopBits == DefaultStopBits) && ((DataBits == 6) || (DataBits == 7) || (DataBits == 8))) {
613     if (LastSettings->StopBits == OneFiveStopBits) {
614       return EFI_INVALID_PARAMETER;
615     }
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;
620       }
621     }
622   }
623 
624   //
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
628   //
629   if (((DataBits < 5 ) || (DataBits > 8)) && (DataBits != 0)) {
630     return EFI_INVALID_PARAMETER;
631   }
632   if (DataBits == 0) {
633     //
634     // use the value of LastDataBits
635     //
636     DevReq.Value = SET_DATA_BITS (LastSettings->DataBits);
637   } else {
638     //
639     // use the value of DataBits
640     //
641     DevReq.Value = SET_DATA_BITS (DataBits);
642   }
643 
644   //
645   // Set Parity
646   //
647   if (Parity == DefaultParity) {
648     Parity = LastSettings->Parity;
649   }
650 
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;
661   }
662 
663   //
664   // Set Stop Bits
665   //
666   if (StopBits == DefaultStopBits) {
667     StopBits = LastSettings->StopBits;
668   }
669 
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;
676   }
677 
678   //
679   // set the rest of the DevReq parameters and perform the usb control transfer
680   // to set the data bits on the device
681   //
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
686 
687   Status = UsbIo->UsbControlTransfer (
688                     UsbIo,
689                     &DevReq,
690                     EfiUsbDataOut,
691                     WDR_SHORT_TIMEOUT,
692                     &ConfigurationValue,
693                     1,
694                     &ReturnValue
695                     );
696   if (EFI_ERROR (Status)) {
697     goto StatusError;
698   }
699   return Status;
700 
701 StatusError:
702   if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
703     return EFI_DEVICE_ERROR;
704   } else {
705     return Status;
706   }
707 }
708 
709 /**
710   Internal function that sets the baudrate on the Usb Serial Device.
711 
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
715                                      will be used instead
716   @param  LastBaudRate[in]           The baud rate value that was previously set
717                                      on the Usb Serial Device
718 
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
723 
724 **/
725 EFI_STATUS
726 EFIAPI
SetBaudRateInternal(IN EFI_USB_IO_PROTOCOL * UsbIo,IN UINT64 BaudRate,IN UINT64 LastBaudRate)727 SetBaudRateInternal (
728   IN EFI_USB_IO_PROTOCOL  *UsbIo,
729   IN UINT64               BaudRate,
730   IN UINT64               LastBaudRate
731   )
732 {
733   EFI_STATUS              Status;
734   EFI_USB_DEVICE_REQUEST  DevReq;
735   UINT32                  ReturnValue;
736   UINT8                   ConfigurationValue;
737   UINT16                  EncodedBaudRate;
738   EFI_TPL                 Tpl;
739 
740   Tpl    = gBS->RaiseTPL(TPL_NOTIFY);
741 
742   //
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
745   //
746   if (BaudRate == 0) {
747     Status = EncodeBaudRateForFtdi (LastBaudRate, &EncodedBaudRate);
748     if (EFI_ERROR (Status)) {
749       gBS->RestoreTPL (Tpl);
750       //
751       // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
752       // succesfull
753       //
754       return Status;
755     }
756     DevReq.Value = EncodedBaudRate;
757   } else {
758     Status = EncodeBaudRateForFtdi (BaudRate, &EncodedBaudRate);
759     if (EFI_ERROR (Status)) {
760       gBS->RestoreTPL (Tpl);
761       //
762       // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
763       // successfull
764       //
765       return Status;
766     }
767     DevReq.Value = EncodedBaudRate;
768   }
769 
770   //
771   // set the remaining parameters of DevReq and perform the usb control transfer
772   // to set the device
773   //
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
778 
779   Status = UsbIo->UsbControlTransfer (
780                     UsbIo,
781                     &DevReq,
782                     EfiUsbDataOut,
783                     WDR_SHORT_TIMEOUT,
784                     &ConfigurationValue,
785                     1,
786                     &ReturnValue
787                     );
788   if (EFI_ERROR (Status)) {
789     goto StatusError;
790   }
791   gBS->RestoreTPL (Tpl);
792   return Status;
793 
794 StatusError:
795   gBS->RestoreTPL (Tpl);
796   if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
797     return EFI_DEVICE_ERROR;
798   } else {
799     return Status;
800   }
801 }
802 
803 /**
804   Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
805   data bits, and stop bits on a serial device.
806 
807   @param  UsbSerialDevice[in]  Pointer to the current instance of the USB Serial
808                                Device.
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
814                                depth.
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
819                                time out value.
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.
829 
830   @retval EFI_SUCCESS          The attributes were set
831   @retval EFI_DEVICE_ERROR     The attributes were not able to be set
832 
833 **/
834 EFI_STATUS
835 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)836 SetAttributesInternal (
837   IN USB_SER_DEV         *UsbSerialDevice,
838   IN UINT64              BaudRate,
839   IN UINT32              ReceiveFifoDepth,
840   IN UINT32              Timeout,
841   IN EFI_PARITY_TYPE     Parity,
842   IN UINT8               DataBits,
843   IN EFI_STOP_BITS_TYPE  StopBits
844   )
845 {
846   EFI_STATUS                Status;
847   EFI_TPL                   Tpl;
848   UART_DEVICE_PATH          *Uart;
849   EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
850 
851   Status = EFI_UNSUPPORTED;
852   Tpl    = gBS->RaiseTPL(TPL_NOTIFY);
853   Uart   = NULL;
854 
855   //
856   // check for invalid combinations of parameters
857   //
858   if (((DataBits >= 6) && (DataBits <= 8)) && (StopBits == OneFiveStopBits)) {
859     return  EFI_INVALID_PARAMETER;
860   }
861 
862   //
863   // set data bits, parity and stop bits
864   //
865   Status = SetDataInternal (
866              UsbSerialDevice->UsbIo,
867              DataBits,
868              Parity,
869              StopBits,
870              &(UsbSerialDevice->LastSettings)
871              );
872   if (EFI_ERROR (Status)) {
873     goto StatusError;
874   }
875   //
876   // set baudrate
877   //
878   Status = SetBaudRateInternal (
879              UsbSerialDevice->UsbIo,
880              BaudRate,
881              UsbSerialDevice->LastSettings.BaudRate
882              );
883   if (EFI_ERROR (Status)){
884     goto StatusError;
885   }
886 
887   //
888   // update the values of UsbSerialDevice->LastSettings and UsbSerialDevice->SerialIo.Mode
889   //
890   if (BaudRate == 0) {
891     UsbSerialDevice->LastSettings.BaudRate   = UsbSerialDevice->LastSettings.BaudRate;
892     UsbSerialDevice->SerialIo.Mode->BaudRate = UsbSerialDevice->LastSettings.BaudRate;
893   } else {
894     UsbSerialDevice->LastSettings.BaudRate   = BaudRate;
895     UsbSerialDevice->SerialIo.Mode->BaudRate = BaudRate;
896   }
897 
898   UsbSerialDevice->LastSettings.Timeout          = FTDI_TIMEOUT;
899   UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;
900 
901   if (Parity == DefaultParity) {
902     UsbSerialDevice->LastSettings.Parity   = UsbSerialDevice->LastSettings.Parity;
903     UsbSerialDevice->SerialIo.Mode->Parity = UsbSerialDevice->LastSettings.Parity;
904   } else {
905     UsbSerialDevice->LastSettings.Parity   = Parity;
906     UsbSerialDevice->SerialIo.Mode->Parity = Parity;
907   }
908   if (DataBits == 0) {
909     UsbSerialDevice->LastSettings.DataBits   = UsbSerialDevice->LastSettings.DataBits;
910     UsbSerialDevice->SerialIo.Mode->DataBits = UsbSerialDevice->LastSettings.DataBits;
911   } else {
912     UsbSerialDevice->LastSettings.DataBits   = DataBits;
913     UsbSerialDevice->SerialIo.Mode->DataBits = DataBits;
914   }
915   if (StopBits == DefaultStopBits) {
916     UsbSerialDevice->LastSettings.StopBits   = UsbSerialDevice->LastSettings.StopBits;
917     UsbSerialDevice->SerialIo.Mode->StopBits = UsbSerialDevice->LastSettings.StopBits;
918   } else {
919     UsbSerialDevice->LastSettings.StopBits   = StopBits;
920     UsbSerialDevice->SerialIo.Mode->StopBits = StopBits;
921   }
922 
923   //
924   // See if the device path node has changed
925   //
926   if (UsbSerialDevice->UartDevicePath.BaudRate == BaudRate &&
927       UsbSerialDevice->UartDevicePath.DataBits == DataBits &&
928       UsbSerialDevice->UartDevicePath.StopBits == StopBits &&
929       UsbSerialDevice->UartDevicePath.Parity == Parity
930       ) {
931     gBS->RestoreTPL (Tpl);
932     return EFI_SUCCESS;
933   }
934 
935   //
936   // Update the device path
937   //
938   UsbSerialDevice->UartDevicePath.BaudRate = BaudRate;
939   UsbSerialDevice->UartDevicePath.DataBits = DataBits;
940   UsbSerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
941   UsbSerialDevice->UartDevicePath.Parity   = (UINT8) Parity;
942 
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;
955         break;
956         }
957         RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
958     }
959   }
960 
961   gBS->RestoreTPL (Tpl);
962   return Status;
963 
964 StatusError:
965   gBS->RestoreTPL (Tpl);
966   if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
967     return EFI_DEVICE_ERROR;
968   } else {
969     return Status;
970   }
971 }
972 
973 /**
974   Internal function that performs a Usb Control Transfer to set the flow control
975   on the Usb Serial Device.
976 
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
980 
981   @retval EFI_SUCCESS                The flow control was set on the Usb Serial
982                                      device
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
986 
987 **/
988 EFI_STATUS
989 EFIAPI
SetFlowControlInternal(IN EFI_USB_IO_PROTOCOL * UsbIo,IN BOOLEAN FlowControlEnable)990 SetFlowControlInternal (
991   IN EFI_USB_IO_PROTOCOL  *UsbIo,
992   IN BOOLEAN              FlowControlEnable
993   )
994 {
995   EFI_STATUS               Status;
996   EFI_USB_DEVICE_REQUEST   DevReq;
997   UINT32                   ReturnValue;
998   UINT8                    ConfigurationValue;
999 
1000   //
1001   // set DevReq.Value based on the value of FlowControlEnable
1002   //
1003   if (!FlowControlEnable) {
1004     DevReq.Value = NO_FLOW_CTRL;
1005   }
1006   if (FlowControlEnable) {
1007     DevReq.Value = XON_XOFF_CTRL;
1008   }
1009   //
1010   // set the remaining DevReq parameters and perform the usb control transfer to
1011   // set the flow control on the device
1012   //
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 (
1018                                  UsbIo,
1019                                  &DevReq,
1020                                  EfiUsbDataOut,
1021                                  WDR_TIMEOUT,
1022                                  &ConfigurationValue,
1023                                  1,
1024                                  &ReturnValue
1025                                  );
1026   if (EFI_ERROR (Status)) {
1027     goto StatusError;
1028   }
1029 
1030   return Status;
1031 
1032 StatusError:
1033   if ((Status != EFI_INVALID_PARAMETER) ||
1034       (Status != EFI_DEVICE_ERROR)      ||
1035       (Status != EFI_UNSUPPORTED)          ) {
1036     return EFI_DEVICE_ERROR;
1037   } else {
1038     return Status;
1039   }
1040 }
1041 
1042 /**
1043   Internal function that performs a Usb Control Transfer to set the Dtr value on
1044   the Usb Serial Device.
1045 
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
1049 
1050   @retval EFI_SUCCESS                The Dtr value was set on the Usb Serial
1051                                      Device
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
1055 
1056 **/
1057 EFI_STATUS
1058 EFIAPI
SetDtrInternal(IN EFI_USB_IO_PROTOCOL * UsbIo,IN BOOLEAN DtrEnable)1059 SetDtrInternal (
1060   IN EFI_USB_IO_PROTOCOL  *UsbIo,
1061   IN BOOLEAN              DtrEnable
1062   )
1063 {
1064   EFI_STATUS              Status;
1065   EFI_USB_DEVICE_REQUEST  DevReq;
1066   UINT32                  ReturnValue;
1067   UINT8                   ConfigurationValue;
1068 
1069   //
1070   // set the value of DevReq.Value based on the value of DtrEnable
1071   //
1072   if (!DtrEnable) {
1073     DevReq.Value = SET_DTR_LOW;
1074   }
1075   if (DtrEnable) {
1076     DevReq.Value = SET_DTR_HIGH;
1077   }
1078   //
1079   // set the remaining attributes of DevReq and perform the usb control transfer
1080   // to set the device
1081   //
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
1086 
1087   Status = UsbIo->UsbControlTransfer (
1088                     UsbIo,
1089                     &DevReq,
1090                     EfiUsbDataOut,
1091                     WDR_TIMEOUT,
1092                     &ConfigurationValue,
1093                     1,
1094                     &ReturnValue
1095                     );
1096   if (EFI_ERROR (Status)) {
1097     goto StatusError;
1098   }
1099   return Status;
1100 
1101 StatusError:
1102   if ((Status != EFI_INVALID_PARAMETER) ||
1103       (Status != EFI_DEVICE_ERROR)      ||
1104       (Status != EFI_UNSUPPORTED)          ) {
1105     return EFI_DEVICE_ERROR;
1106   } else {
1107     return Status;
1108   }
1109 }
1110 
1111 /**
1112   Internal function that performs a Usb Control Transfer to set the Dtr value on
1113   the Usb Serial Device.
1114 
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
1118 
1119   @retval EFI_SUCCESS                The Rts value was set on the Usb Serial
1120                                      Device
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
1124 
1125 **/
1126 EFI_STATUS
1127 EFIAPI
SetRtsInternal(IN EFI_USB_IO_PROTOCOL * UsbIo,IN BOOLEAN RtsEnable)1128 SetRtsInternal (
1129   IN EFI_USB_IO_PROTOCOL  *UsbIo,
1130   IN BOOLEAN              RtsEnable
1131   )
1132 {
1133   EFI_STATUS              Status;
1134   EFI_USB_DEVICE_REQUEST  DevReq;
1135   UINT32                  ReturnValue;
1136   UINT8                   ConfigurationValue;
1137 
1138   //
1139   // set DevReq.Value based on the value of RtsEnable
1140   //
1141   if (!RtsEnable) {
1142     DevReq.Value = SET_RTS_LOW;
1143   }
1144   if (RtsEnable) {
1145     DevReq.Value = SET_RTS_HIGH;
1146   }
1147 
1148   //
1149   // set the remaining parameters of DevReq and perform the usb control transfer
1150   // to set the values on the device
1151   //
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
1156 
1157   Status = UsbIo->UsbControlTransfer (
1158                     UsbIo,
1159                     &DevReq,
1160                     EfiUsbDataOut,
1161                     WDR_TIMEOUT,
1162                     &ConfigurationValue,
1163                     1,
1164                     &ReturnValue
1165                     );
1166   if (EFI_ERROR (Status)) {
1167     goto StatusError;
1168   }
1169 
1170   return Status;
1171 
1172 StatusError:
1173   if ((Status != EFI_INVALID_PARAMETER) ||
1174       (Status != EFI_DEVICE_ERROR)      ||
1175       (Status != EFI_UNSUPPORTED)          ) {
1176     return EFI_DEVICE_ERROR;
1177   } else {
1178     return Status;
1179   }
1180 }
1181 
1182 /**
1183   Internal function that checks for valid control values and sets the control
1184   bits on the Usb Serial Device.
1185 
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
1191 
1192   @retval EFI_SUCCESS                The control bits were set on the Usb Serial
1193                                      Device
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
1197 
1198 **/
1199 EFI_STATUS
1200 EFIAPI
SetControlBitsInternal(IN USB_SER_DEV * UsbSerialDevice,IN CONTROL_BITS * Control)1201 SetControlBitsInternal (
1202   IN USB_SER_DEV   *UsbSerialDevice,
1203   IN CONTROL_BITS  *Control
1204   )
1205 {
1206   EFI_STATUS                    Status;
1207   UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
1208   EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath;
1209 
1210   //
1211   // check for invalid control parameters hardware and software loopback enabled
1212   // must always be set to FALSE
1213   //
1214   Control->HardwareLoopBack = FALSE;
1215   Control->SoftwareLoopBack = FALSE;
1216 
1217   //
1218   // set hardware flow control
1219   //
1220   Status  = SetFlowControlInternal (
1221               UsbSerialDevice->UsbIo,
1222               Control->HardwareFlowControl
1223               );
1224   if (EFI_ERROR (Status)) {
1225     goto StatusError;
1226   }
1227 
1228   //
1229   // set Dtr state
1230   //
1231   Status = SetDtrInternal (UsbSerialDevice->UsbIo, Control->DtrState);
1232   if (EFI_ERROR (Status)) {
1233     goto StatusError;
1234   }
1235 
1236   //
1237   // set Rts state
1238   //
1239   Status = SetRtsInternal (UsbSerialDevice->UsbIo, Control->RtsState);
1240   if (EFI_ERROR (Status)){
1241     goto StatusError;
1242   }
1243 
1244   //
1245   // update the remaining control values for UsbSerialDevice->ControlValues
1246   //
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;
1252 
1253   Status = EFI_SUCCESS;
1254   //
1255   // Update the device path to have the correct flow control values
1256   //
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;
1268         }
1269         break;
1270       }
1271       RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
1272     }
1273   }
1274 
1275   return Status;
1276 
1277 StatusError:
1278   if ((Status != EFI_INVALID_PARAMETER) ||
1279       (Status != EFI_DEVICE_ERROR)      ||
1280       (Status != EFI_UNSUPPORTED)          ) {
1281     return EFI_DEVICE_ERROR;
1282   } else {
1283     return Status;
1284   }
1285 }
1286 
1287 /**
1288   Internal function that calculates the Control value used by GetControlBits()
1289   based on the status and control values of the Usb Serial Device.
1290 
1291   @param  UsbSerialDevice[in]        Handle to the Usb Serial Devie whose status
1292                                      and control values are being used to set
1293                                      Control
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
1297                                      Device
1298 
1299   @retval EFI_SUCCESS                The value of Control was successfully
1300                                      calculated
1301 
1302 **/
1303 EFI_STATUS
1304 EFIAPI
GetControlBitsInternal(IN USB_SER_DEV * UsbSerialDevice,OUT UINT32 * Control)1305 GetControlBitsInternal (
1306   IN USB_SER_DEV  *UsbSerialDevice,
1307   OUT UINT32      *Control
1308   )
1309 {
1310   *Control = 0;
1311 
1312   //
1313   // Check the values of UsbSerialDevice->Status Values and modify control
1314   // accordingly these values correspond to the modem status register
1315   //
1316   if (UsbSerialDevice->StatusValues.CtsState) {
1317     *Control |= EFI_SERIAL_CLEAR_TO_SEND;
1318   }
1319   if (UsbSerialDevice->StatusValues.DsrState) {
1320     *Control |= EFI_SERIAL_DATA_SET_READY;
1321   }
1322   if (UsbSerialDevice->StatusValues.RiState) {
1323     *Control |= EFI_SERIAL_RING_INDICATE;
1324   }
1325   if (UsbSerialDevice->StatusValues.SdState) {
1326     *Control |= EFI_SERIAL_CARRIER_DETECT;
1327   }
1328 
1329   //
1330   // check the values of UsbSerialDevice->ControlValues and modify control
1331   // accordingly these values correspond to the values of the Modem Control
1332   // Register
1333   //
1334   if (UsbSerialDevice->ControlValues.DtrState) {
1335     *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
1336   }
1337   if (UsbSerialDevice->ControlValues.RtsState) {
1338     *Control |= EFI_SERIAL_REQUEST_TO_SEND;
1339   }
1340   if (UsbSerialDevice->ControlValues.HardwareLoopBack) {
1341     *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
1342   }
1343   if (UsbSerialDevice->ControlValues.HardwareFlowControl) {
1344     *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1345   }
1346   //
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
1349   //
1350   if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
1351     *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
1352     *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
1353   }
1354   //
1355   // check for software loopback enable in UsbSerialDevice->ControlValues
1356   //
1357   if (UsbSerialDevice->ControlValues.SoftwareLoopBack) {
1358     *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
1359   }
1360 
1361   return EFI_SUCCESS;
1362 }
1363 
1364 /**
1365   Resets the USB Serial Device
1366 
1367   This function is the internal method for resetting the device and is called by
1368   SerialReset()
1369 
1370   @param  UsbSerialDevice[in]  A pointer to the USB Serial device
1371 
1372   @retval EFI_SUCCESS          The device was reset
1373   @retval EFI_DEVICE_ERROR     The device could not be reset
1374 
1375 **/
1376 EFI_STATUS
1377 EFIAPI
ResetInternal(IN USB_SER_DEV * UsbSerialDevice)1378 ResetInternal (
1379   IN USB_SER_DEV  *UsbSerialDevice
1380   )
1381 {
1382   EFI_STATUS              Status;
1383   EFI_USB_DEVICE_REQUEST  DevReq;
1384   UINT8                   ConfigurationValue;
1385   UINT32                  ReturnValue;
1386 
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
1392 
1393   Status = UsbSerialDevice->UsbIo->UsbControlTransfer (
1394                                      UsbSerialDevice->UsbIo,
1395                                      &DevReq,
1396                                      EfiUsbDataIn,
1397                                      WDR_TIMEOUT,
1398                                      &ConfigurationValue,
1399                                      1,
1400                                      &ReturnValue
1401                                      );
1402   if (EFI_ERROR (Status)) {
1403     return EFI_DEVICE_ERROR;
1404   }
1405 
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
1411 
1412   Status = UsbSerialDevice->UsbIo->UsbControlTransfer (
1413                                      UsbSerialDevice->UsbIo,
1414                                      &DevReq,
1415                                      EfiUsbDataIn,
1416                                      WDR_TIMEOUT,
1417                                      &ConfigurationValue,
1418                                      1,
1419                                      &ReturnValue
1420                                      );
1421   if (EFI_ERROR (Status)) {
1422     return EFI_DEVICE_ERROR;
1423   }
1424   return Status;
1425 }
1426 
1427 /**
1428   Entrypoint of USB Serial Driver.
1429 
1430   This function is the entrypoint of USB Serial Driver. It installs
1431   Driver Binding Protocols together with Component Name Protocols.
1432 
1433   @param  ImageHandle[in]       The firmware allocated handle for the EFI image.
1434   @param  SystemTable[in]       A pointer to the EFI System Table.
1435 
1436   @retval EFI_SUCCESS           The entry point is executed successfully.
1437 
1438 **/
1439 EFI_STATUS
1440 EFIAPI
FtdiUsbSerialEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1441 FtdiUsbSerialEntryPoint (
1442   IN EFI_HANDLE        ImageHandle,
1443   IN EFI_SYSTEM_TABLE  *SystemTable
1444   )
1445 {
1446   EFI_STATUS  Status;
1447 
1448   Status = EfiLibInstallDriverBindingComponentName2 (
1449              ImageHandle,
1450              SystemTable,
1451              &gUsbSerialDriverBinding,
1452              ImageHandle,
1453              &gUsbSerialComponentName,
1454              &gUsbSerialComponentName2
1455              );
1456   ASSERT_EFI_ERROR (Status);
1457   return EFI_SUCCESS;
1458 }
1459 
1460 /**
1461   Unload function for the Usb Serial Driver.
1462 
1463   @param  ImageHandle[in]    The allocated handle for the EFI image
1464 
1465   @retval EFI_SUCCESS        The driver was unloaded successfully
1466 **/
1467 EFI_STATUS
1468 EFIAPI
FtdiUsbSerialUnload(IN EFI_HANDLE ImageHandle)1469 FtdiUsbSerialUnload (
1470   IN EFI_HANDLE  ImageHandle
1471   )
1472 {
1473   EFI_STATUS  Status;
1474   EFI_HANDLE  *HandleBuffer;
1475   UINTN       HandleCount;
1476   UINTN       Index;
1477 
1478   //
1479   // Retrieve all handles in the handle database
1480   //
1481   Status = gBS->LocateHandleBuffer (
1482                   AllHandles,
1483                   NULL,
1484                   NULL,
1485                   &HandleCount,
1486                   &HandleBuffer
1487                   );
1488   if (EFI_ERROR (Status)) {
1489     return Status;
1490   }
1491 
1492   //
1493   // Disconnect the driver from the handles in the handle database
1494   //
1495   for (Index = 0; Index < HandleCount; Index++) {
1496     Status = gBS->DisconnectController (
1497                     HandleBuffer[Index],
1498                     gImageHandle,
1499                     NULL
1500                     );
1501   }
1502 
1503   //
1504   // Free the handle array
1505   //
1506   FreePool (HandleBuffer);
1507 
1508   //
1509   // Uninstall protocols installed by the driver in its entrypoint
1510   //
1511   Status = gBS->UninstallMultipleProtocolInterfaces (
1512                   ImageHandle,
1513                   &gEfiDriverBindingProtocolGuid,
1514                   &gUsbSerialDriverBinding,
1515                   &gEfiComponentNameProtocolGuid,
1516                   &gUsbSerialComponentName,
1517                   &gEfiComponentName2ProtocolGuid,
1518                   &gUsbSerialComponentName2,
1519                   NULL
1520                   );
1521   if (EFI_ERROR (Status)) {
1522     return Status;
1523   }
1524 
1525   return EFI_SUCCESS;
1526 }
1527 
1528 /**
1529   Check whether USB Serial driver supports this device.
1530 
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.
1534 
1535   @retval EFI_SUCCESS                The driver supports this controller.
1536   @retval other                      This device isn't supported.
1537 
1538 **/
1539 EFI_STATUS
1540 EFIAPI
UsbSerialDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1541 UsbSerialDriverBindingSupported (
1542   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1543   IN EFI_HANDLE                   Controller,
1544   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
1545   )
1546 {
1547   EFI_STATUS           Status;
1548   EFI_USB_IO_PROTOCOL  *UsbIo;
1549   UART_DEVICE_PATH     *UartNode;
1550   UART_FLOW_CONTROL_DEVICE_PATH        *FlowControlNode;
1551   UINTN                                Index;
1552   UINTN                                EntryCount;
1553   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY  *OpenInfoBuffer;
1554   BOOLEAN                              HasFlowControl;
1555   EFI_DEVICE_PATH_PROTOCOL             *DevicePath;
1556   EFI_DEVICE_PATH_PROTOCOL             *ParentDevicePath;
1557 
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)) {
1565         goto Error;
1566       }
1567       FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);
1568       if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
1569         goto Error;
1570       }
1571     }
1572   }
1573 
1574   //
1575   // Check if USB I/O Protocol is attached on the controller handle.
1576   //
1577   Status = gBS->OpenProtocol (
1578                   Controller,
1579                   &gEfiUsbIoProtocolGuid,
1580                   (VOID **) &UsbIo,
1581                   This->DriverBindingHandle,
1582                   Controller,
1583                   EFI_OPEN_PROTOCOL_BY_DRIVER
1584                   );
1585   if (Status == EFI_ALREADY_STARTED) {
1586     if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
1587       return EFI_SUCCESS;
1588     }
1589     Status = gBS->OpenProtocolInformation (
1590                     Controller,
1591                     &gEfiUsbIoProtocolGuid,
1592                     &OpenInfoBuffer,
1593                     &EntryCount
1594                     );
1595     if (EFI_ERROR (Status)) {
1596       return Status;
1597     }
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,
1605                         Controller,
1606                         EFI_OPEN_PROTOCOL_GET_PROTOCOL
1607                         );
1608         if (!EFI_ERROR (Status)) {
1609           HasFlowControl = ContainsFlowControl (RemainingDevicePath);
1610           if (HasFlowControl ^ ContainsFlowControl (DevicePath)) {
1611             Status = EFI_UNSUPPORTED;
1612           }
1613         }
1614         break;
1615       }
1616     }
1617     FreePool (OpenInfoBuffer);
1618     return Status;
1619   }
1620 
1621   if (EFI_ERROR (Status)) {
1622     return Status;
1623   }
1624 
1625   gBS->CloseProtocol (
1626          Controller,
1627          &gEfiUsbIoProtocolGuid,
1628          This->DriverBindingHandle,
1629          Controller
1630          );
1631 
1632   Status = gBS->OpenProtocol (
1633                   Controller,
1634                   &gEfiDevicePathProtocolGuid,
1635                   (VOID **) &ParentDevicePath,
1636                   This->DriverBindingHandle,
1637                   Controller,
1638                   EFI_OPEN_PROTOCOL_BY_DRIVER
1639                   );
1640   if (Status == EFI_ALREADY_STARTED) {
1641     return EFI_SUCCESS;
1642   }
1643   if (EFI_ERROR (Status)) {
1644     return Status;
1645   }
1646 
1647   //
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.
1650   //
1651   Status = EFI_SUCCESS;
1652 
1653   if (!IsUsbSerial (UsbIo)) {
1654     Status = EFI_UNSUPPORTED;
1655     goto Error;
1656   }
1657 
1658 Error:
1659   gBS->CloseProtocol (
1660          Controller,
1661          &gEfiDevicePathProtocolGuid,
1662          This->DriverBindingHandle,
1663          Controller
1664          );
1665   return Status;
1666 }
1667 
1668 /**
1669   Starts the USB Serial device with this driver.
1670 
1671   This function produces initializes the USB Serial device and
1672   produces the Serial IO Protocol.
1673 
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.
1678 
1679   @retval EFI_SUCCESS                The controller is controlled by the usb USB
1680                                      Serial driver.
1681   @retval EFI_UNSUPPORTED            No interrupt endpoint can be found.
1682   @retval Other                      This controller cannot be started.
1683 
1684 **/
1685 EFI_STATUS
1686 EFIAPI
UsbSerialDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1687 UsbSerialDriverBindingStart (
1688   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1689   IN EFI_HANDLE                   Controller,
1690   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
1691   )
1692 {
1693   EFI_STATUS                          Status;
1694   EFI_USB_IO_PROTOCOL                 *UsbIo;
1695   USB_SER_DEV                         *UsbSerialDevice;
1696   UINT8                               EndpointNumber;
1697   EFI_USB_ENDPOINT_DESCRIPTOR         EndpointDescriptor;
1698   UINT8                               Index;
1699   BOOLEAN                             FoundIn;
1700   BOOLEAN                             FoundOut;
1701   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
1702   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
1703   UINTN                               EntryCount;
1704   EFI_SERIAL_IO_PROTOCOL              *SerialIo;
1705   UART_DEVICE_PATH                    *Uart;
1706   UART_FLOW_CONTROL_DEVICE_PATH       *FlowControl;
1707   UINT32                              Control;
1708   EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
1709 
1710   UsbSerialDevice = AllocateZeroPool (sizeof (USB_SER_DEV));
1711   ASSERT (UsbSerialDevice != NULL);
1712 
1713   //
1714   // Get the Parent Device path
1715   //
1716   Status = gBS->OpenProtocol (
1717                   Controller,
1718                   &gEfiDevicePathProtocolGuid,
1719                   (VOID **) &ParentDevicePath,
1720                   This->DriverBindingHandle,
1721                   Controller,
1722                   EFI_OPEN_PROTOCOL_BY_DRIVER
1723                   );
1724   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1725     goto ErrorExit1;
1726   }
1727 
1728   //
1729   // Open USB I/O Protocol
1730   //
1731   Status = gBS->OpenProtocol (
1732                   Controller,
1733                   &gEfiUsbIoProtocolGuid,
1734                   (VOID **) &UsbIo,
1735                   This->DriverBindingHandle,
1736                   Controller,
1737                   EFI_OPEN_PROTOCOL_BY_DRIVER
1738                   );
1739   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1740     goto ErrorExit1;
1741   }
1742 
1743   if (Status == EFI_ALREADY_STARTED) {
1744     if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
1745       FreePool (UsbSerialDevice);
1746       return EFI_SUCCESS;
1747     }
1748 
1749     //
1750     // Check to see if a child handle exists
1751     //
1752     Status = gBS->OpenProtocolInformation (
1753                     Controller,
1754                     &gEfiSerialIoProtocolGuid,
1755                     &OpenInfoBuffer,
1756                     &EntryCount
1757                     );
1758     if (EFI_ERROR (Status)) {
1759       goto ErrorExit1;
1760     }
1761 
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,
1770                         Controller,
1771                         EFI_OPEN_PROTOCOL_GET_PROTOCOL
1772                         );
1773         if (EFI_ERROR (Status)) {
1774         }
1775         if (!EFI_ERROR (Status)) {
1776           Uart = (UART_DEVICE_PATH *) RemainingDevicePath;
1777           Status = SerialIo->SetAttributes (
1778                                SerialIo,
1779                                Uart->BaudRate,
1780                                SerialIo->Mode->ReceiveFifoDepth,
1781                                SerialIo->Mode->Timeout,
1782                                (EFI_PARITY_TYPE) Uart->Parity,
1783                                Uart->DataBits,
1784                                (EFI_STOP_BITS_TYPE) Uart->StopBits
1785                                );
1786           FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
1787           if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {
1788             Status = SerialIo->GetControl (
1789                                  SerialIo,
1790                                  &Control
1791                                  );
1792             if (!EFI_ERROR (Status)) {
1793               if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) {
1794                 Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1795               } else {
1796                 Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1797               }
1798               //
1799               // Clear bits that are not allowed to be passed to SetControl
1800               //
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);
1807             }
1808           }
1809         }
1810         break;
1811       }
1812     }
1813     FreePool (OpenInfoBuffer);
1814     return Status;
1815   }
1816 
1817   if (RemainingDevicePath != NULL) {
1818     if (IsDevicePathEnd (RemainingDevicePath)) {
1819       return EFI_SUCCESS;
1820     }
1821   }
1822 
1823   UsbSerialDevice->UsbIo = UsbIo;
1824 
1825   //
1826   // Get interface & endpoint descriptor
1827   //
1828   UsbIo->UsbGetInterfaceDescriptor (
1829            UsbIo,
1830            &UsbSerialDevice->InterfaceDescriptor
1831            );
1832 
1833   EndpointNumber = UsbSerialDevice->InterfaceDescriptor.NumEndpoints;
1834 
1835   //
1836   // Traverse endpoints to find the IN and OUT endpoints that will send and
1837   // receive data.
1838   //
1839   FoundIn = FALSE;
1840   FoundOut = FALSE;
1841   for (Index = 0; Index < EndpointNumber; Index++) {
1842 
1843     Status = UsbIo->UsbGetEndpointDescriptor (
1844                       UsbIo,
1845                       Index,
1846                       &EndpointDescriptor
1847                       );
1848     if (EFI_ERROR (Status)) {
1849       return Status;
1850     }
1851 
1852     if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_OUT) {
1853       //
1854       // Set the Out endpoint device
1855       //
1856       CopyMem (
1857         &UsbSerialDevice->OutEndpointDescriptor,
1858         &EndpointDescriptor,
1859         sizeof(EndpointDescriptor)
1860         );
1861       FoundOut = TRUE;
1862     }
1863 
1864     if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_IN) {
1865       //
1866       // Set the In endpoint device
1867       //
1868       CopyMem (
1869         &UsbSerialDevice->InEndpointDescriptor,
1870         &EndpointDescriptor,
1871         sizeof(EndpointDescriptor)
1872         );
1873       FoundIn = TRUE;
1874     }
1875   }
1876 
1877   if (!FoundIn || !FoundOut) {
1878     //
1879     // No interrupt endpoint found, then return unsupported.
1880     //
1881     Status = EFI_UNSUPPORTED;
1882     goto ErrorExit;
1883   }
1884   //
1885   // set the initial values of UsbSerialDevice->LastSettings to the default
1886   // values
1887   //
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;
1894 
1895   //
1896   // set the initial values of UsbSerialDevice->ControlValues
1897   //
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;
1903 
1904   //
1905   // set the values of UsbSerialDevice->UartDevicePath
1906   //
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);
1911 
1912   //
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;
1919 
1920   Status = SetAttributesInternal (
1921              UsbSerialDevice,
1922              UsbSerialDevice->LastSettings.BaudRate,
1923              UsbSerialDevice->LastSettings.ReceiveFifoDepth,
1924              UsbSerialDevice->LastSettings.Timeout,
1925              UsbSerialDevice->LastSettings.Parity,
1926              UsbSerialDevice->LastSettings.DataBits,
1927              UsbSerialDevice->LastSettings.StopBits
1928              );
1929 
1930   ASSERT_EFI_ERROR (Status);
1931 
1932   Status = SetControlBitsInternal (
1933              UsbSerialDevice,
1934              &(UsbSerialDevice->ControlValues)
1935              );
1936 
1937   ASSERT_EFI_ERROR (Status);
1938 
1939   //
1940   // Publish Serial GUID and protocol
1941   //
1942 
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;
1950 
1951   //
1952   // Set the static Serial IO modes that will display when running
1953   // "sermode" within the UEFI shell.
1954   //
1955 
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;
1961 
1962   UsbSerialDevice->ParentDevicePath = ParentDevicePath;
1963   UsbSerialDevice->ControllerHandle = NULL;
1964   FlowControl                       = NULL;
1965 
1966   //
1967   // Allocate space for the receive buffer
1968   //
1969   UsbSerialDevice->DataBuffer = AllocateZeroPool (SW_FIFO_DEPTH);
1970 
1971   //
1972   // Initialize data buffer pointers.
1973   // Head==Tail = true means buffer is empty.
1974   //
1975   UsbSerialDevice->DataBufferHead = 0;
1976   UsbSerialDevice->DataBufferTail = 0;
1977 
1978   UsbSerialDevice->ControllerNameTable = NULL;
1979   AddUnicodeString2 (
1980     "eng",
1981     gUsbSerialComponentName.SupportedLanguages,
1982     &UsbSerialDevice->ControllerNameTable,
1983     L"FTDI USB Serial Adapter",
1984     TRUE
1985     );
1986   AddUnicodeString2 (
1987     "en",
1988     gUsbSerialComponentName2.SupportedLanguages,
1989     &UsbSerialDevice->ControllerNameTable,
1990     L"FTDI USB Serial Adapter",
1991     FALSE
1992     );
1993 
1994   Status = SetInitialStatus (UsbSerialDevice);
1995   ASSERT_EFI_ERROR (Status);
1996 
1997   //
1998   // Create a polling loop to check for input
1999   //
2000 
2001   gBS->CreateEvent (
2002          EVT_TIMER | EVT_NOTIFY_SIGNAL,
2003          TPL_CALLBACK,
2004          UsbSerialDriverCheckInput,
2005          UsbSerialDevice,
2006          &(UsbSerialDevice->PollingLoop)
2007          );
2008   //
2009   // add code to set trigger time based on baud rate
2010   // setting to 0.5s for now
2011   //
2012   gBS->SetTimer (
2013          UsbSerialDevice->PollingLoop,
2014          TimerPeriodic,
2015          EFI_TIMER_PERIOD_MILLISECONDS (500)
2016          );
2017 
2018   //
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
2021   //
2022   if (RemainingDevicePath != NULL) {
2023     CopyMem (
2024       &UsbSerialDevice->UartDevicePath,
2025       RemainingDevicePath,
2026       sizeof (UART_DEVICE_PATH)
2027       );
2028     FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
2029     if (IsUartFlowControlNode (FlowControl)) {
2030       UsbSerialDevice->FlowControlDevicePath.FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap);
2031     } else {
2032       FlowControl = NULL;
2033     }
2034   }
2035 
2036   //
2037   // Build the device path by appending the UART node to the parent device path
2038   //
2039   UsbSerialDevice->DevicePath = AppendDevicePathNode (
2040                                   ParentDevicePath,
2041                                   (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->UartDevicePath
2042                                   );
2043   //
2044   // Continue building the device path by appending the flow control node
2045   //
2046   TempDevicePath = UsbSerialDevice->DevicePath;
2047   UsbSerialDevice->DevicePath = AppendDevicePathNode (
2048                                   TempDevicePath,
2049                                   (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->FlowControlDevicePath
2050                                   );
2051   FreePool (TempDevicePath);
2052 
2053   if (UsbSerialDevice->DevicePath == NULL) {
2054     Status = EFI_OUT_OF_RESOURCES;
2055     goto ErrorExit;
2056   }
2057 
2058   //
2059   // Install protocol interfaces for the device
2060   //
2061   Status = gBS->InstallMultipleProtocolInterfaces (
2062                   &UsbSerialDevice->ControllerHandle,
2063                   &gEfiDevicePathProtocolGuid,
2064                   UsbSerialDevice->DevicePath,
2065                   &gEfiSerialIoProtocolGuid,
2066                   &UsbSerialDevice->SerialIo,
2067                   NULL
2068                   );
2069   if (EFI_ERROR (Status)){
2070     goto ErrorExit;
2071   }
2072 
2073   //
2074   // Open for child device
2075   //
2076   Status = gBS->OpenProtocol (
2077                  Controller,
2078                  &gEfiUsbIoProtocolGuid,
2079                  (VOID **) &UsbIo,
2080                  This->DriverBindingHandle,
2081                  UsbSerialDevice->ControllerHandle,
2082                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
2083                  );
2084 
2085   UsbSerialDevice->Shutdown = FALSE;
2086 
2087   return EFI_SUCCESS;
2088 
2089 ErrorExit:
2090   //
2091   // Error handler
2092   //
2093 
2094   Status = gBS->UninstallMultipleProtocolInterfaces (
2095                   Controller,
2096                   &gEfiSerialIoProtocolGuid,
2097                   &UsbSerialDevice->SerialIo,
2098                   NULL
2099                   );
2100   if (EFI_ERROR (Status)) {
2101     goto ErrorExit1;
2102   }
2103 
2104   FreePool (UsbSerialDevice->DataBuffer);
2105   FreePool (UsbSerialDevice);
2106 
2107   UsbSerialDevice = NULL;
2108   gBS->CloseProtocol (
2109          Controller,
2110          &gEfiUsbIoProtocolGuid,
2111          This->DriverBindingHandle,
2112          Controller
2113          );
2114 
2115 ErrorExit1:
2116   return Status;
2117 }
2118 
2119 /**
2120   Stop the USB Serial device handled by this driver.
2121 
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.
2126 
2127   @retval EFI_SUCCESS                The device was stopped.
2128   @retval EFI_UNSUPPORTED            Serial IO Protocol is not installed on
2129                                      Controller.
2130   @retval EFI_DEVICE_ERROR           The device could not be stopped due to a
2131                                      device error.
2132   @retval Others                     Fail to uninstall protocols attached on the
2133                                      device.
2134 
2135 **/
2136 EFI_STATUS
2137 EFIAPI
UsbSerialDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)2138 UsbSerialDriverBindingStop (
2139   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
2140   IN  EFI_HANDLE                   Controller,
2141   IN  UINTN                        NumberOfChildren,
2142   IN  EFI_HANDLE                   *ChildHandleBuffer
2143   )
2144 {
2145   EFI_STATUS                Status;
2146   EFI_SERIAL_IO_PROTOCOL    *SerialIo;
2147   EFI_USB_IO_PROTOCOL       *UsbIo;
2148   USB_SER_DEV               *UsbSerialDevice;
2149   UINTN                     Index;
2150   BOOLEAN                   AllChildrenStopped;
2151 
2152   Status = EFI_SUCCESS;
2153   UsbSerialDevice = NULL;
2154 
2155   if (NumberOfChildren == 0) {
2156     //
2157     // Close the driver
2158     //
2159     Status = gBS->CloseProtocol (
2160                     Controller,
2161                     &gEfiUsbIoProtocolGuid,
2162                     This->DriverBindingHandle,
2163                     Controller
2164                     );
2165     Status = gBS->CloseProtocol (
2166                     Controller,
2167                     &gEfiDevicePathProtocolGuid,
2168                     This->DriverBindingHandle,
2169                     Controller
2170                     );
2171     return Status;
2172   }
2173 
2174   AllChildrenStopped = TRUE;
2175 
2176   for (Index = 0; Index < NumberOfChildren ;Index++) {
2177     Status = gBS->OpenProtocol (
2178                     ChildHandleBuffer[Index],
2179                     &gEfiSerialIoProtocolGuid,
2180                     (VOID **) &SerialIo,
2181                     This->DriverBindingHandle,
2182                     Controller,
2183                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
2184                     );
2185     if (Status == EFI_SUCCESS) {//!EFI_ERROR (Status)) {
2186       UsbSerialDevice = USB_SER_DEV_FROM_THIS (SerialIo);
2187       Status = gBS->CloseProtocol (
2188                       Controller,
2189                       &gEfiUsbIoProtocolGuid,
2190                       This->DriverBindingHandle,
2191                       ChildHandleBuffer[Index]
2192                       );
2193       Status = gBS->UninstallMultipleProtocolInterfaces (
2194                       ChildHandleBuffer[Index],
2195                       &gEfiDevicePathProtocolGuid,
2196                       UsbSerialDevice->DevicePath,
2197                       &gEfiSerialIoProtocolGuid,
2198                       &UsbSerialDevice->SerialIo,
2199                       NULL
2200                       );
2201 
2202       if (EFI_ERROR (Status)) {
2203         gBS->OpenProtocol (
2204                Controller,
2205                &gEfiUsbIoProtocolGuid,
2206                (VOID **) &UsbIo,
2207                This->DriverBindingHandle,
2208                ChildHandleBuffer[Index],
2209                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
2210                );
2211       } else {
2212         if (UsbSerialDevice->DevicePath != NULL) {
2213           gBS->FreePool (UsbSerialDevice->DevicePath);
2214         }
2215         gBS->SetTimer (
2216                UsbSerialDevice->PollingLoop,
2217                TimerCancel,
2218                0
2219                );
2220         gBS->CloseEvent (UsbSerialDevice->PollingLoop);
2221         UsbSerialDevice->Shutdown = TRUE;
2222         FreeUnicodeStringTable (UsbSerialDevice->ControllerNameTable);
2223         FreePool (UsbSerialDevice->DataBuffer);
2224         FreePool (UsbSerialDevice);
2225       }
2226     }
2227     if (EFI_ERROR (Status)) {
2228       AllChildrenStopped = FALSE;
2229     }
2230   }
2231 
2232   if (!AllChildrenStopped) {
2233     return EFI_DEVICE_ERROR;
2234   }
2235   return EFI_SUCCESS;
2236 }
2237 
2238 //
2239 // Serial IO Member Functions
2240 //
2241 
2242 /**
2243   Reset the serial device.
2244 
2245   @param  This[in]              Protocol instance pointer.
2246 
2247   @retval EFI_SUCCESS           The device was reset.
2248   @retval EFI_DEVICE_ERROR      The serial device could not be reset.
2249 
2250 **/
2251 EFI_STATUS
2252 EFIAPI
SerialReset(IN EFI_SERIAL_IO_PROTOCOL * This)2253 SerialReset (
2254   IN EFI_SERIAL_IO_PROTOCOL  *This
2255   )
2256 {
2257   EFI_STATUS    Status;
2258   USB_SER_DEV  *UsbSerialDevice;
2259 
2260   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2261   Status          = ResetInternal (UsbSerialDevice);
2262   if (EFI_ERROR (Status)){
2263     return EFI_DEVICE_ERROR;
2264   }
2265   return Status;
2266 }
2267 
2268 /**
2269   Set the control bits on a serial device.
2270 
2271   @param  This[in]             Protocol instance pointer.
2272   @param  Control[in]          Set the bits of Control that are settable.
2273 
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.
2277 
2278 **/
2279 EFI_STATUS
2280 EFIAPI
SetControlBits(IN EFI_SERIAL_IO_PROTOCOL * This,IN UINT32 Control)2281 SetControlBits (
2282   IN EFI_SERIAL_IO_PROTOCOL  *This,
2283   IN UINT32                  Control
2284   )
2285 {
2286   EFI_STATUS    Status;
2287   USB_SER_DEV   *UsbSerialDevice;
2288   CONTROL_BITS  ControlBits;
2289 
2290   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2291 
2292   //
2293   // check for invalid control parameters
2294   //
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;
2301   }
2302 
2303   //
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
2307   //
2308   ControlBits.HardwareLoopBack = FALSE;
2309   ControlBits.SoftwareLoopBack = FALSE;
2310   //
2311   // check for hardware flow control
2312   //
2313   if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
2314     ControlBits.HardwareFlowControl = TRUE;
2315   } else {
2316     ControlBits.HardwareFlowControl = FALSE;
2317   }
2318   //
2319   // check for DTR enabled
2320   //
2321   if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
2322     ControlBits.DtrState = TRUE;
2323   } else {
2324     ControlBits.DtrState = FALSE;
2325   }
2326   //
2327   // check for RTS enabled
2328   //
2329   if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
2330     ControlBits.RtsState = TRUE;
2331   } else {
2332     ControlBits.RtsState = FALSE;
2333   }
2334 
2335   //
2336   // set the control values with a call to SetControlBitsInternal()
2337   //
2338   Status = SetControlBitsInternal (UsbSerialDevice, &ControlBits);
2339 
2340   return Status;
2341 }
2342 
2343 /**
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
2346   device.
2347 
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
2354                                depth.
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
2359                                time out value.
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.
2369 
2370   @retval EFI_SUCCESS          The attributes were set
2371   @retval EFI_DEVICE_ERROR     The attributes were not able to be
2372 
2373 **/
2374 EFI_STATUS
2375 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)2376 SetAttributes (
2377   IN EFI_SERIAL_IO_PROTOCOL  *This,
2378   IN UINT64                  BaudRate,
2379   IN UINT32                  ReceiveFifoDepth,
2380   IN UINT32                  Timeout,
2381   IN EFI_PARITY_TYPE         Parity,
2382   IN UINT8                   DataBits,
2383   IN EFI_STOP_BITS_TYPE      StopBits
2384   )
2385 {
2386 
2387   EFI_STATUS   Status;
2388   USB_SER_DEV  *UsbSerialDevice;
2389 
2390   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2391 
2392   Status = SetAttributesInternal (
2393              UsbSerialDevice,
2394              BaudRate,
2395              ReceiveFifoDepth,
2396              Timeout,
2397              Parity,
2398              DataBits,
2399              StopBits
2400              );
2401   if (EFI_ERROR (Status)) {
2402     return Status;
2403   }
2404 
2405   return Status;
2406 }
2407 
2408 
2409 /**
2410   Retrieves the status of the control bits on a serial device.
2411 
2412   @param  This[in]               Protocol instance pointer.
2413   @param  Control[out]           A pointer to return the current Control signals
2414                                  from the serial device.
2415 
2416   @retval EFI_SUCCESS            The control bits were read from the serial
2417                                  device.
2418   @retval EFI_DEVICE_ERROR       The serial device is not functioning correctly.
2419 
2420 **/
2421 EFI_STATUS
2422 EFIAPI
GetControlBits(IN EFI_SERIAL_IO_PROTOCOL * This,OUT UINT32 * Control)2423 GetControlBits (
2424   IN EFI_SERIAL_IO_PROTOCOL  *This,
2425   OUT UINT32                 *Control
2426   )
2427 {
2428   USB_SER_DEV  *UsbSerialDevice;
2429   EFI_STATUS   Status;
2430 
2431   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2432 
2433   *Control        = 0;
2434 
2435   Status = GetControlBitsInternal (UsbSerialDevice, Control);
2436 
2437   if (EFI_ERROR (Status)) {
2438     return EFI_DEVICE_ERROR;
2439   }
2440   return Status;
2441 }
2442 
2443 /**
2444   Reads data from a serial device.
2445 
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.
2450 
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.
2454 
2455 **/
2456 EFI_STATUS
2457 EFIAPI
ReadSerialIo(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,OUT VOID * Buffer)2458 ReadSerialIo (
2459   IN EFI_SERIAL_IO_PROTOCOL  *This,
2460   IN OUT UINTN               *BufferSize,
2461   OUT VOID                   *Buffer
2462   )
2463 {
2464   UINTN        Index;
2465   UINTN        RemainingCallerBufferSize;
2466   USB_SER_DEV  *UsbSerialDevice;
2467   EFI_STATUS   Status;
2468 
2469 
2470   if (*BufferSize == 0) {
2471     return EFI_SUCCESS;
2472   }
2473 
2474   if (Buffer == NULL) {
2475     return EFI_DEVICE_ERROR;
2476   }
2477 
2478   Status          = EFI_SUCCESS;
2479   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2480 
2481   //
2482   // Clear out any data that we already have in our internal buffer
2483   //
2484   for (Index = 0; Index < *BufferSize; Index++) {
2485     if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
2486       break;
2487     }
2488 
2489     //
2490     // Still have characters in the buffer to return
2491     //
2492     ((UINT8 *)Buffer)[Index] = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];
2493     UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;
2494   }
2495 
2496   //
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
2499   // caller's buffer
2500   //
2501   if (Index != *BufferSize) {
2502     RemainingCallerBufferSize = *BufferSize - Index;
2503     Status = ReadDataFromUsb (
2504                UsbSerialDevice,
2505                &RemainingCallerBufferSize,
2506                (VOID *)(((CHAR8 *)Buffer) + Index)
2507                );
2508     if (!EFI_ERROR (Status)) {
2509       *BufferSize = RemainingCallerBufferSize + Index;
2510     } else {
2511       *BufferSize = Index;
2512     }
2513   }
2514 
2515   if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
2516     //
2517     // Data buffer has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY flag
2518     //
2519     UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
2520   } else {
2521     //
2522     // There is some leftover data, clear EFI_SERIAL_INPUT_BUFFER_EMPTY flag
2523     //
2524     UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
2525   }
2526   return Status;
2527 }
2528 
2529 /**
2530   Writes data to a serial device.
2531 
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
2536 
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.
2540 
2541 **/
2542 EFI_STATUS
2543 EFIAPI
WriteSerialIo(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,IN VOID * Buffer)2544 WriteSerialIo (
2545   IN EFI_SERIAL_IO_PROTOCOL  *This,
2546   IN OUT UINTN               *BufferSize,
2547   IN VOID                    *Buffer
2548   )
2549 {
2550   EFI_STATUS   Status;
2551   USB_SER_DEV  *UsbSerialDevice;
2552   EFI_TPL      Tpl;
2553 
2554   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2555 
2556   if (UsbSerialDevice->Shutdown) {
2557     return EFI_DEVICE_ERROR;
2558   }
2559 
2560   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
2561 
2562   Status = UsbSerialDataTransfer (
2563              UsbSerialDevice,
2564              EfiUsbDataOut,
2565              Buffer,
2566              BufferSize,
2567              FTDI_TIMEOUT
2568              );
2569 
2570   gBS->RestoreTPL (Tpl);
2571   if (EFI_ERROR (Status)) {
2572     if (Status == EFI_TIMEOUT){
2573       return Status;
2574     } else {
2575       return EFI_DEVICE_ERROR;
2576     }
2577   }
2578 
2579   return EFI_SUCCESS;
2580 }
2581