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