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