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