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