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