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