• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 resetting 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                              Control;
1714   EFI_DEVICE_PATH_PROTOCOL            *TempDevicePath;
1715 
1716   UsbSerialDevice = AllocateZeroPool (sizeof (USB_SER_DEV));
1717   ASSERT (UsbSerialDevice != NULL);
1718 
1719   //
1720   // Get the Parent Device path
1721   //
1722   Status = gBS->OpenProtocol (
1723                   Controller,
1724                   &gEfiDevicePathProtocolGuid,
1725                   (VOID **) &ParentDevicePath,
1726                   This->DriverBindingHandle,
1727                   Controller,
1728                   EFI_OPEN_PROTOCOL_BY_DRIVER
1729                   );
1730   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1731     goto ErrorExit1;
1732   }
1733 
1734   //
1735   // Open USB I/O Protocol
1736   //
1737   Status = gBS->OpenProtocol (
1738                   Controller,
1739                   &gEfiUsbIoProtocolGuid,
1740                   (VOID **) &UsbIo,
1741                   This->DriverBindingHandle,
1742                   Controller,
1743                   EFI_OPEN_PROTOCOL_BY_DRIVER
1744                   );
1745   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
1746     goto ErrorExit1;
1747   }
1748 
1749   if (Status == EFI_ALREADY_STARTED) {
1750     if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
1751       FreePool (UsbSerialDevice);
1752       return EFI_SUCCESS;
1753     }
1754 
1755     //
1756     // Check to see if a child handle exists
1757     //
1758     Status = gBS->OpenProtocolInformation (
1759                     Controller,
1760                     &gEfiSerialIoProtocolGuid,
1761                     &OpenInfoBuffer,
1762                     &EntryCount
1763                     );
1764     if (EFI_ERROR (Status)) {
1765       goto ErrorExit1;
1766     }
1767 
1768     Status = EFI_ALREADY_STARTED;
1769     for (Index = 0; Index < EntryCount; Index++) {
1770       if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
1771         Status = gBS->OpenProtocol (
1772                         OpenInfoBuffer[Index].ControllerHandle,
1773                         &gEfiSerialIoProtocolGuid,
1774                         (VOID **) &SerialIo,
1775                         This->DriverBindingHandle,
1776                         Controller,
1777                         EFI_OPEN_PROTOCOL_GET_PROTOCOL
1778                         );
1779         if (EFI_ERROR (Status)) {
1780         }
1781         if (!EFI_ERROR (Status)) {
1782           Uart = (UART_DEVICE_PATH *) RemainingDevicePath;
1783           Status = SerialIo->SetAttributes (
1784                                SerialIo,
1785                                Uart->BaudRate,
1786                                SerialIo->Mode->ReceiveFifoDepth,
1787                                SerialIo->Mode->Timeout,
1788                                (EFI_PARITY_TYPE) Uart->Parity,
1789                                Uart->DataBits,
1790                                (EFI_STOP_BITS_TYPE) Uart->StopBits
1791                                );
1792           FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
1793           if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {
1794             Status = SerialIo->GetControl (
1795                                  SerialIo,
1796                                  &Control
1797                                  );
1798             if (!EFI_ERROR (Status)) {
1799               if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) {
1800                 Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1801               } else {
1802                 Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
1803               }
1804               //
1805               // Clear bits that are not allowed to be passed to SetControl
1806               //
1807               Control &= (EFI_SERIAL_REQUEST_TO_SEND |
1808                           EFI_SERIAL_DATA_TERMINAL_READY |
1809                           EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |
1810                           EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
1811                           EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);
1812               Status = SerialIo->SetControl (SerialIo, Control);
1813             }
1814           }
1815         }
1816         break;
1817       }
1818     }
1819     FreePool (OpenInfoBuffer);
1820     return Status;
1821   }
1822 
1823   if (RemainingDevicePath != NULL) {
1824     if (IsDevicePathEnd (RemainingDevicePath)) {
1825       return EFI_SUCCESS;
1826     }
1827   }
1828 
1829   UsbSerialDevice->UsbIo = UsbIo;
1830 
1831   //
1832   // Get interface & endpoint descriptor
1833   //
1834   UsbIo->UsbGetInterfaceDescriptor (
1835            UsbIo,
1836            &UsbSerialDevice->InterfaceDescriptor
1837            );
1838 
1839   EndpointNumber = UsbSerialDevice->InterfaceDescriptor.NumEndpoints;
1840 
1841   //
1842   // Traverse endpoints to find the IN and OUT endpoints that will send and
1843   // receive data.
1844   //
1845   FoundIn = FALSE;
1846   FoundOut = FALSE;
1847   for (Index = 0; Index < EndpointNumber; Index++) {
1848 
1849     Status = UsbIo->UsbGetEndpointDescriptor (
1850                       UsbIo,
1851                       Index,
1852                       &EndpointDescriptor
1853                       );
1854     if (EFI_ERROR (Status)) {
1855       return Status;
1856     }
1857 
1858     if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_OUT) {
1859       //
1860       // Set the Out endpoint device
1861       //
1862       CopyMem (
1863         &UsbSerialDevice->OutEndpointDescriptor,
1864         &EndpointDescriptor,
1865         sizeof(EndpointDescriptor)
1866         );
1867       FoundOut = TRUE;
1868     }
1869 
1870     if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_IN) {
1871       //
1872       // Set the In endpoint device
1873       //
1874       CopyMem (
1875         &UsbSerialDevice->InEndpointDescriptor,
1876         &EndpointDescriptor,
1877         sizeof(EndpointDescriptor)
1878         );
1879       FoundIn = TRUE;
1880     }
1881   }
1882 
1883   if (!FoundIn || !FoundOut) {
1884     //
1885     // No interrupt endpoint found, then return unsupported.
1886     //
1887     Status = EFI_UNSUPPORTED;
1888     goto ErrorExit;
1889   }
1890   //
1891   // set the initial values of UsbSerialDevice->LastSettings to the default
1892   // values
1893   //
1894   UsbSerialDevice->LastSettings.BaudRate         = 115200;
1895   UsbSerialDevice->LastSettings.DataBits         = 8;
1896   UsbSerialDevice->LastSettings.Parity           = NoParity;
1897   UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;
1898   UsbSerialDevice->LastSettings.StopBits         = OneStopBit;
1899   UsbSerialDevice->LastSettings.Timeout          = FTDI_TIMEOUT;
1900 
1901   //
1902   // set the initial values of UsbSerialDevice->ControlValues
1903   //
1904   UsbSerialDevice->ControlValues.DtrState            = FALSE;
1905   UsbSerialDevice->ControlValues.RtsState            = FALSE;
1906   UsbSerialDevice->ControlValues.HardwareFlowControl = FALSE;
1907   UsbSerialDevice->ControlValues.HardwareLoopBack    = FALSE;
1908   UsbSerialDevice->ControlValues.SoftwareLoopBack    = FALSE;
1909 
1910   //
1911   // set the values of UsbSerialDevice->UartDevicePath
1912   //
1913   UsbSerialDevice->UartDevicePath.Header.Type    = MESSAGING_DEVICE_PATH;
1914   UsbSerialDevice->UartDevicePath.Header.SubType = MSG_UART_DP;
1915   UsbSerialDevice->UartDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_DEVICE_PATH));
1916   UsbSerialDevice->UartDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8);
1917 
1918   //
1919   // set the values of UsbSerialDevice->FlowControlDevicePath
1920   UsbSerialDevice->FlowControlDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
1921   UsbSerialDevice->FlowControlDevicePath.Header.SubType = MSG_VENDOR_DP;
1922   UsbSerialDevice->FlowControlDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_FLOW_CONTROL_DEVICE_PATH));
1923   UsbSerialDevice->FlowControlDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_FLOW_CONTROL_DEVICE_PATH)) >> 8);
1924   UsbSerialDevice->FlowControlDevicePath.FlowControlMap = 0;
1925 
1926   Status = SetAttributesInternal (
1927              UsbSerialDevice,
1928              UsbSerialDevice->LastSettings.BaudRate,
1929              UsbSerialDevice->LastSettings.ReceiveFifoDepth,
1930              UsbSerialDevice->LastSettings.Timeout,
1931              UsbSerialDevice->LastSettings.Parity,
1932              UsbSerialDevice->LastSettings.DataBits,
1933              UsbSerialDevice->LastSettings.StopBits
1934              );
1935 
1936   ASSERT_EFI_ERROR (Status);
1937 
1938   Status = SetControlBitsInternal (
1939              UsbSerialDevice,
1940              &(UsbSerialDevice->ControlValues)
1941              );
1942 
1943   ASSERT_EFI_ERROR (Status);
1944 
1945   //
1946   // Publish Serial GUID and protocol
1947   //
1948 
1949   UsbSerialDevice->Signature              = USB_SER_DEV_SIGNATURE;
1950   UsbSerialDevice->SerialIo.Reset         = SerialReset;
1951   UsbSerialDevice->SerialIo.SetControl    = SetControlBits;
1952   UsbSerialDevice->SerialIo.SetAttributes = SetAttributes;
1953   UsbSerialDevice->SerialIo.GetControl    = GetControlBits;
1954   UsbSerialDevice->SerialIo.Read          = ReadSerialIo;
1955   UsbSerialDevice->SerialIo.Write         = WriteSerialIo;
1956 
1957   //
1958   // Set the static Serial IO modes that will display when running
1959   // "sermode" within the UEFI shell.
1960   //
1961 
1962   UsbSerialDevice->SerialIo.Mode->Timeout  = 0;
1963   UsbSerialDevice->SerialIo.Mode->BaudRate = 115200;
1964   UsbSerialDevice->SerialIo.Mode->DataBits = 8;
1965   UsbSerialDevice->SerialIo.Mode->Parity   = 1;
1966   UsbSerialDevice->SerialIo.Mode->StopBits = 1;
1967 
1968   UsbSerialDevice->ParentDevicePath = ParentDevicePath;
1969   UsbSerialDevice->ControllerHandle = NULL;
1970   FlowControl                       = NULL;
1971 
1972   //
1973   // Allocate space for the receive buffer
1974   //
1975   UsbSerialDevice->DataBuffer = AllocateZeroPool (SW_FIFO_DEPTH);
1976 
1977   //
1978   // Initialize data buffer pointers.
1979   // Head==Tail = true means buffer is empty.
1980   //
1981   UsbSerialDevice->DataBufferHead = 0;
1982   UsbSerialDevice->DataBufferTail = 0;
1983 
1984   UsbSerialDevice->ControllerNameTable = NULL;
1985   AddUnicodeString2 (
1986     "eng",
1987     gUsbSerialComponentName.SupportedLanguages,
1988     &UsbSerialDevice->ControllerNameTable,
1989     L"FTDI USB Serial Adapter",
1990     TRUE
1991     );
1992   AddUnicodeString2 (
1993     "en",
1994     gUsbSerialComponentName2.SupportedLanguages,
1995     &UsbSerialDevice->ControllerNameTable,
1996     L"FTDI USB Serial Adapter",
1997     FALSE
1998     );
1999 
2000   Status = SetInitialStatus (UsbSerialDevice);
2001   ASSERT_EFI_ERROR (Status);
2002 
2003   //
2004   // Create a polling loop to check for input
2005   //
2006 
2007   gBS->CreateEvent (
2008          EVT_TIMER | EVT_NOTIFY_SIGNAL,
2009          TPL_CALLBACK,
2010          UsbSerialDriverCheckInput,
2011          UsbSerialDevice,
2012          &(UsbSerialDevice->PollingLoop)
2013          );
2014   //
2015   // add code to set trigger time based on baud rate
2016   // setting to 0.5s for now
2017   //
2018   gBS->SetTimer (
2019          UsbSerialDevice->PollingLoop,
2020          TimerPeriodic,
2021          EFI_TIMER_PERIOD_MILLISECONDS (500)
2022          );
2023 
2024   //
2025   // Check if the remaining device path is null. If it is not null change the settings
2026   // of the device to match those on the device path
2027   //
2028   if (RemainingDevicePath != NULL) {
2029     CopyMem (
2030       &UsbSerialDevice->UartDevicePath,
2031       RemainingDevicePath,
2032       sizeof (UART_DEVICE_PATH)
2033       );
2034     FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
2035     if (IsUartFlowControlNode (FlowControl)) {
2036       UsbSerialDevice->FlowControlDevicePath.FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap);
2037     } else {
2038       FlowControl = NULL;
2039     }
2040   }
2041 
2042   //
2043   // Build the device path by appending the UART node to the parent device path
2044   //
2045   UsbSerialDevice->DevicePath = AppendDevicePathNode (
2046                                   ParentDevicePath,
2047                                   (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->UartDevicePath
2048                                   );
2049   //
2050   // Continue building the device path by appending the flow control node
2051   //
2052   TempDevicePath = UsbSerialDevice->DevicePath;
2053   UsbSerialDevice->DevicePath = AppendDevicePathNode (
2054                                   TempDevicePath,
2055                                   (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->FlowControlDevicePath
2056                                   );
2057   FreePool (TempDevicePath);
2058 
2059   if (UsbSerialDevice->DevicePath == NULL) {
2060     Status = EFI_OUT_OF_RESOURCES;
2061     goto ErrorExit;
2062   }
2063 
2064   //
2065   // Install protocol interfaces for the device
2066   //
2067   Status = gBS->InstallMultipleProtocolInterfaces (
2068                   &UsbSerialDevice->ControllerHandle,
2069                   &gEfiDevicePathProtocolGuid,
2070                   UsbSerialDevice->DevicePath,
2071                   &gEfiSerialIoProtocolGuid,
2072                   &UsbSerialDevice->SerialIo,
2073                   NULL
2074                   );
2075   if (EFI_ERROR (Status)){
2076     goto ErrorExit;
2077   }
2078 
2079   //
2080   // Open for child device
2081   //
2082   Status = gBS->OpenProtocol (
2083                  Controller,
2084                  &gEfiUsbIoProtocolGuid,
2085                  (VOID **) &UsbIo,
2086                  This->DriverBindingHandle,
2087                  UsbSerialDevice->ControllerHandle,
2088                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
2089                  );
2090 
2091   UsbSerialDevice->Shutdown = FALSE;
2092 
2093   return EFI_SUCCESS;
2094 
2095 ErrorExit:
2096   //
2097   // Error handler
2098   //
2099 
2100   Status = gBS->UninstallMultipleProtocolInterfaces (
2101                   Controller,
2102                   &gEfiSerialIoProtocolGuid,
2103                   &UsbSerialDevice->SerialIo,
2104                   NULL
2105                   );
2106   if (EFI_ERROR (Status)) {
2107     goto ErrorExit1;
2108   }
2109 
2110   FreePool (UsbSerialDevice->DataBuffer);
2111   FreePool (UsbSerialDevice);
2112 
2113   UsbSerialDevice = NULL;
2114   gBS->CloseProtocol (
2115          Controller,
2116          &gEfiUsbIoProtocolGuid,
2117          This->DriverBindingHandle,
2118          Controller
2119          );
2120 
2121 ErrorExit1:
2122   return Status;
2123 }
2124 
2125 /**
2126   Stop the USB Serial device handled by this driver.
2127 
2128   @param  This[in]                   The USB Serial driver binding protocol.
2129   @param  Controller[in]             The controller to release.
2130   @param  NumberOfChildren[in]       The number of handles in ChildHandleBuffer.
2131   @param  ChildHandleBuffer[in]      The array of child handle.
2132 
2133   @retval EFI_SUCCESS                The device was stopped.
2134   @retval EFI_UNSUPPORTED            Serial IO Protocol is not installed on
2135                                      Controller.
2136   @retval EFI_DEVICE_ERROR           The device could not be stopped due to a
2137                                      device error.
2138   @retval Others                     Fail to uninstall protocols attached on the
2139                                      device.
2140 
2141 **/
2142 EFI_STATUS
2143 EFIAPI
UsbSerialDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)2144 UsbSerialDriverBindingStop (
2145   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
2146   IN  EFI_HANDLE                   Controller,
2147   IN  UINTN                        NumberOfChildren,
2148   IN  EFI_HANDLE                   *ChildHandleBuffer
2149   )
2150 {
2151   EFI_STATUS                Status;
2152   EFI_SERIAL_IO_PROTOCOL    *SerialIo;
2153   EFI_USB_IO_PROTOCOL       *UsbIo;
2154   USB_SER_DEV               *UsbSerialDevice;
2155   UINTN                     Index;
2156   BOOLEAN                   AllChildrenStopped;
2157 
2158   Status = EFI_SUCCESS;
2159   UsbSerialDevice = NULL;
2160 
2161   if (NumberOfChildren == 0) {
2162     //
2163     // Close the driver
2164     //
2165     Status = gBS->CloseProtocol (
2166                     Controller,
2167                     &gEfiUsbIoProtocolGuid,
2168                     This->DriverBindingHandle,
2169                     Controller
2170                     );
2171     Status = gBS->CloseProtocol (
2172                     Controller,
2173                     &gEfiDevicePathProtocolGuid,
2174                     This->DriverBindingHandle,
2175                     Controller
2176                     );
2177     return Status;
2178   }
2179 
2180   AllChildrenStopped = TRUE;
2181 
2182   for (Index = 0; Index < NumberOfChildren ;Index++) {
2183     Status = gBS->OpenProtocol (
2184                     ChildHandleBuffer[Index],
2185                     &gEfiSerialIoProtocolGuid,
2186                     (VOID **) &SerialIo,
2187                     This->DriverBindingHandle,
2188                     Controller,
2189                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
2190                     );
2191     if (Status == EFI_SUCCESS) {//!EFI_ERROR (Status)) {
2192       UsbSerialDevice = USB_SER_DEV_FROM_THIS (SerialIo);
2193       Status = gBS->CloseProtocol (
2194                       Controller,
2195                       &gEfiUsbIoProtocolGuid,
2196                       This->DriverBindingHandle,
2197                       ChildHandleBuffer[Index]
2198                       );
2199       Status = gBS->UninstallMultipleProtocolInterfaces (
2200                       ChildHandleBuffer[Index],
2201                       &gEfiDevicePathProtocolGuid,
2202                       UsbSerialDevice->DevicePath,
2203                       &gEfiSerialIoProtocolGuid,
2204                       &UsbSerialDevice->SerialIo,
2205                       NULL
2206                       );
2207 
2208       if (EFI_ERROR (Status)) {
2209         gBS->OpenProtocol (
2210                Controller,
2211                &gEfiUsbIoProtocolGuid,
2212                (VOID **) &UsbIo,
2213                This->DriverBindingHandle,
2214                ChildHandleBuffer[Index],
2215                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
2216                );
2217       } else {
2218         if (UsbSerialDevice->DevicePath != NULL) {
2219           gBS->FreePool (UsbSerialDevice->DevicePath);
2220         }
2221         gBS->SetTimer (
2222                UsbSerialDevice->PollingLoop,
2223                TimerCancel,
2224                0
2225                );
2226         gBS->CloseEvent (UsbSerialDevice->PollingLoop);
2227         UsbSerialDevice->Shutdown = TRUE;
2228         FreeUnicodeStringTable (UsbSerialDevice->ControllerNameTable);
2229         FreePool (UsbSerialDevice->DataBuffer);
2230         FreePool (UsbSerialDevice);
2231       }
2232     }
2233     if (EFI_ERROR (Status)) {
2234       AllChildrenStopped = FALSE;
2235     }
2236   }
2237 
2238   if (!AllChildrenStopped) {
2239     return EFI_DEVICE_ERROR;
2240   }
2241   return EFI_SUCCESS;
2242 }
2243 
2244 //
2245 // Serial IO Member Functions
2246 //
2247 
2248 /**
2249   Reset the serial device.
2250 
2251   @param  This[in]              Protocol instance pointer.
2252 
2253   @retval EFI_SUCCESS           The device was reset.
2254   @retval EFI_DEVICE_ERROR      The serial device could not be reset.
2255 
2256 **/
2257 EFI_STATUS
2258 EFIAPI
SerialReset(IN EFI_SERIAL_IO_PROTOCOL * This)2259 SerialReset (
2260   IN EFI_SERIAL_IO_PROTOCOL  *This
2261   )
2262 {
2263   EFI_STATUS    Status;
2264   USB_SER_DEV  *UsbSerialDevice;
2265 
2266   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2267   Status          = ResetInternal (UsbSerialDevice);
2268   if (EFI_ERROR (Status)){
2269     return EFI_DEVICE_ERROR;
2270   }
2271   return Status;
2272 }
2273 
2274 /**
2275   Set the control bits on a serial device.
2276 
2277   @param  This[in]             Protocol instance pointer.
2278   @param  Control[in]          Set the bits of Control that are settable.
2279 
2280   @retval EFI_SUCCESS          The new control bits were set on the serial device.
2281   @retval EFI_UNSUPPORTED      The serial device does not support this operation.
2282   @retval EFI_DEVICE_ERROR     The serial device is not functioning correctly.
2283 
2284 **/
2285 EFI_STATUS
2286 EFIAPI
SetControlBits(IN EFI_SERIAL_IO_PROTOCOL * This,IN UINT32 Control)2287 SetControlBits (
2288   IN EFI_SERIAL_IO_PROTOCOL  *This,
2289   IN UINT32                  Control
2290   )
2291 {
2292   EFI_STATUS    Status;
2293   USB_SER_DEV   *UsbSerialDevice;
2294   CONTROL_BITS  ControlBits;
2295 
2296   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2297 
2298   //
2299   // check for invalid control parameters
2300   //
2301   if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND          |
2302                     EFI_SERIAL_DATA_TERMINAL_READY      |
2303                     EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |
2304                     EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
2305                     EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0 ) {
2306     return EFI_UNSUPPORTED;
2307   }
2308 
2309   //
2310   // check the control parameters and set the correct setting for
2311   // the paramerts of ControlBits
2312   // both loopback enables are always set to FALSE
2313   //
2314   ControlBits.HardwareLoopBack = FALSE;
2315   ControlBits.SoftwareLoopBack = FALSE;
2316   //
2317   // check for hardware flow control
2318   //
2319   if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
2320     ControlBits.HardwareFlowControl = TRUE;
2321   } else {
2322     ControlBits.HardwareFlowControl = FALSE;
2323   }
2324   //
2325   // check for DTR enabled
2326   //
2327   if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
2328     ControlBits.DtrState = TRUE;
2329   } else {
2330     ControlBits.DtrState = FALSE;
2331   }
2332   //
2333   // check for RTS enabled
2334   //
2335   if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
2336     ControlBits.RtsState = TRUE;
2337   } else {
2338     ControlBits.RtsState = FALSE;
2339   }
2340 
2341   //
2342   // set the control values with a call to SetControlBitsInternal()
2343   //
2344   Status = SetControlBitsInternal (UsbSerialDevice, &ControlBits);
2345 
2346   return Status;
2347 }
2348 
2349 /**
2350   calls SetAttributesInternal() to set the baud rate, receive FIFO depth,
2351   transmit/receive time out, parity, data buts, and stop bits on a serial
2352   device.
2353 
2354   @param  This[in]             Protocol instance pointer.
2355   @param  BaudRate[in]         The requested baud rate. A BaudRate value of 0
2356                                will use the device's default interface speed.
2357   @param  ReveiveFifoDepth[in] The requested depth of the FIFO on the receive
2358                                side of the serial interface. A ReceiveFifoDepth
2359                                value of 0 will use the device's default FIFO
2360                                depth.
2361   @param  Timeout[in]          The requested time out for a single character in
2362                                microseconds.This timeout applies to both the
2363                                transmit and receive side of the interface. A
2364                                Timeout value of 0 will use the device's default
2365                                time out value.
2366   @param  Parity[in]           The type of parity to use on this serial device.
2367                                A Parity value of DefaultParity will use the
2368                                device's default parity value.
2369   @param  DataBits[in]         The number of data bits to use on the serial
2370                                device. A DataBit vaule of 0 will use the
2371                                device's default data bit setting.
2372   @param  StopBits[in]         The number of stop bits to use on this serial
2373                                device. A StopBits value of DefaultStopBits will
2374                                use the device's default number of stop bits.
2375 
2376   @retval EFI_SUCCESS          The attributes were set
2377   @retval EFI_DEVICE_ERROR     The attributes were not able to be
2378 
2379 **/
2380 EFI_STATUS
2381 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)2382 SetAttributes (
2383   IN EFI_SERIAL_IO_PROTOCOL  *This,
2384   IN UINT64                  BaudRate,
2385   IN UINT32                  ReceiveFifoDepth,
2386   IN UINT32                  Timeout,
2387   IN EFI_PARITY_TYPE         Parity,
2388   IN UINT8                   DataBits,
2389   IN EFI_STOP_BITS_TYPE      StopBits
2390   )
2391 {
2392 
2393   EFI_STATUS   Status;
2394   USB_SER_DEV  *UsbSerialDevice;
2395 
2396   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2397 
2398   Status = SetAttributesInternal (
2399              UsbSerialDevice,
2400              BaudRate,
2401              ReceiveFifoDepth,
2402              Timeout,
2403              Parity,
2404              DataBits,
2405              StopBits
2406              );
2407   if (EFI_ERROR (Status)) {
2408     return Status;
2409   }
2410 
2411   return Status;
2412 }
2413 
2414 
2415 /**
2416   Retrieves the status of the control bits on a serial device.
2417 
2418   @param  This[in]               Protocol instance pointer.
2419   @param  Control[out]           A pointer to return the current Control signals
2420                                  from the serial device.
2421 
2422   @retval EFI_SUCCESS            The control bits were read from the serial
2423                                  device.
2424   @retval EFI_DEVICE_ERROR       The serial device is not functioning correctly.
2425 
2426 **/
2427 EFI_STATUS
2428 EFIAPI
GetControlBits(IN EFI_SERIAL_IO_PROTOCOL * This,OUT UINT32 * Control)2429 GetControlBits (
2430   IN EFI_SERIAL_IO_PROTOCOL  *This,
2431   OUT UINT32                 *Control
2432   )
2433 {
2434   USB_SER_DEV  *UsbSerialDevice;
2435   EFI_STATUS   Status;
2436 
2437   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2438 
2439   *Control        = 0;
2440 
2441   Status = GetControlBitsInternal (UsbSerialDevice, Control);
2442 
2443   if (EFI_ERROR (Status)) {
2444     return EFI_DEVICE_ERROR;
2445   }
2446   return Status;
2447 }
2448 
2449 /**
2450   Reads data from a serial device.
2451 
2452   @param  This[in]                   Protocol instance pointer.
2453   @param  BufferSize[in, out]        On input, the size of the Buffer. On output,
2454                                      the amount of data returned in Buffer.
2455   @param  Buffer[out]                The buffer to return the data into.
2456 
2457   @retval EFI_SUCCESS                The data was read.
2458   @retval EFI_DEVICE_ERROR           The device reported an error.
2459   @retval EFI_TIMEOUT                The data write was stopped due to a timeout.
2460 
2461 **/
2462 EFI_STATUS
2463 EFIAPI
ReadSerialIo(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,OUT VOID * Buffer)2464 ReadSerialIo (
2465   IN EFI_SERIAL_IO_PROTOCOL  *This,
2466   IN OUT UINTN               *BufferSize,
2467   OUT VOID                   *Buffer
2468   )
2469 {
2470   UINTN        Index;
2471   UINTN        RemainingCallerBufferSize;
2472   USB_SER_DEV  *UsbSerialDevice;
2473   EFI_STATUS   Status;
2474 
2475 
2476   if (*BufferSize == 0) {
2477     return EFI_SUCCESS;
2478   }
2479 
2480   if (Buffer == NULL) {
2481     return EFI_DEVICE_ERROR;
2482   }
2483 
2484   Status          = EFI_SUCCESS;
2485   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2486 
2487   //
2488   // Clear out any data that we already have in our internal buffer
2489   //
2490   for (Index = 0; Index < *BufferSize; Index++) {
2491     if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
2492       break;
2493     }
2494 
2495     //
2496     // Still have characters in the buffer to return
2497     //
2498     ((UINT8 *)Buffer)[Index] = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];
2499     UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;
2500   }
2501 
2502   //
2503   // If we haven't filled the caller's buffer using data that we already had on
2504   // hand We need to generate an additional USB request to try and fill the
2505   // caller's buffer
2506   //
2507   if (Index != *BufferSize) {
2508     RemainingCallerBufferSize = *BufferSize - Index;
2509     Status = ReadDataFromUsb (
2510                UsbSerialDevice,
2511                &RemainingCallerBufferSize,
2512                (VOID *)(((CHAR8 *)Buffer) + Index)
2513                );
2514     if (!EFI_ERROR (Status)) {
2515       *BufferSize = RemainingCallerBufferSize + Index;
2516     } else {
2517       *BufferSize = Index;
2518     }
2519   }
2520 
2521   if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
2522     //
2523     // Data buffer has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY flag
2524     //
2525     UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
2526   } else {
2527     //
2528     // There is some leftover data, clear EFI_SERIAL_INPUT_BUFFER_EMPTY flag
2529     //
2530     UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
2531   }
2532   return Status;
2533 }
2534 
2535 /**
2536   Writes data to a serial device.
2537 
2538   @param  This[in]                   Protocol instance pointer.
2539   @param  BufferSize[in, out]        On input, the size of the Buffer. On output,
2540                                      the amount of data actually written.
2541   @param  Buffer[in]                 The buffer of data to write
2542 
2543   @retval EFI_SUCCESS                The data was written.
2544   @retval EFI_DEVICE_ERROR           The device reported an error.
2545   @retval EFI_TIMEOUT                The data write was stopped due to a timeout.
2546 
2547 **/
2548 EFI_STATUS
2549 EFIAPI
WriteSerialIo(IN EFI_SERIAL_IO_PROTOCOL * This,IN OUT UINTN * BufferSize,IN VOID * Buffer)2550 WriteSerialIo (
2551   IN EFI_SERIAL_IO_PROTOCOL  *This,
2552   IN OUT UINTN               *BufferSize,
2553   IN VOID                    *Buffer
2554   )
2555 {
2556   EFI_STATUS   Status;
2557   USB_SER_DEV  *UsbSerialDevice;
2558   EFI_TPL      Tpl;
2559 
2560   UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
2561 
2562   if (UsbSerialDevice->Shutdown) {
2563     return EFI_DEVICE_ERROR;
2564   }
2565 
2566   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
2567 
2568   Status = UsbSerialDataTransfer (
2569              UsbSerialDevice,
2570              EfiUsbDataOut,
2571              Buffer,
2572              BufferSize,
2573              FTDI_TIMEOUT
2574              );
2575 
2576   gBS->RestoreTPL (Tpl);
2577   if (EFI_ERROR (Status)) {
2578     if (Status == EFI_TIMEOUT){
2579       return Status;
2580     } else {
2581       return EFI_DEVICE_ERROR;
2582     }
2583   }
2584 
2585   return EFI_SUCCESS;
2586 }
2587