123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580 |
- /** @file
- USB Serial Driver that manages USB to Serial and produces Serial IO Protocol.
- Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
- Portions Copyright 2012 Ashley DeSimone
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- //
- // Tested with VEND_ID 0x0403, DEVICE_ID 0x6001
- //
- // Driver starts the device with the following values:
- // 115200, No parity, 8 data bits, 1 stop bit, No Flow control
- //
- #include "FtdiUsbSerialDriver.h"
- //
- // Table of supported devices. This is the device information that this
- // driver was developed with. Add other FTDI devices as needed.
- //
- USB_DEVICE gUSBDeviceList[] = {
- {VID_FTDI, DID_FTDI_FT232},
- {0,0}
- };
- //
- // USB Serial Driver Global Variables
- //
- EFI_DRIVER_BINDING_PROTOCOL gUsbSerialDriverBinding = {
- UsbSerialDriverBindingSupported,
- UsbSerialDriverBindingStart,
- UsbSerialDriverBindingStop,
- 0xa,
- NULL,
- NULL
- };
- //
- // Table with the nearest power of 2 for the numbers 0-15
- //
- UINT8 gRoundedPowersOf2[16] = { 0, 2, 2, 4, 4, 4, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16 };
- /**
- Check to see if the device path node is the Flow control node
- @param[in] FlowControl The device path node to be checked
- @retval TRUE It is the flow control node
- @retval FALSE It is not the flow control node
- **/
- BOOLEAN
- IsUartFlowControlNode (
- IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl
- )
- {
- return (BOOLEAN) (
- (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) &&
- (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid))
- );
- }
- /**
- Checks the device path to see if it contains flow control.
- @param[in] DevicePath The device path to be checked
- @retval TRUE It contains flow control
- @retval FALSE It does not contain flow control
- **/
- BOOLEAN
- ContainsFlowControl (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
- {
- while (!IsDevicePathEnd (DevicePath)) {
- if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH *) DevicePath)) {
- return TRUE;
- }
- DevicePath = NextDevicePathNode (DevicePath);
- }
- return FALSE;
- }
- /**
- Transfer the data between the device and host.
- This function transfers the data between the device and host.
- BOT transfer is composed of three phases: Command, Data, and Status.
- This is the Data phase.
- @param UsbBot[in] The USB BOT device
- @param DataDir[in] The direction of the data
- @param Data[in, out] The buffer to hold data
- @param TransLen[in, out] The expected length of the data
- @param Timeout[in] The time to wait the command to complete
- @retval EFI_SUCCESS The data is transferred
- @retval EFI_SUCCESS No data to transfer
- @retval EFI_NOT_READY The device return NAK to the transfer
- @retval Others Failed to transfer data
- **/
- EFI_STATUS
- UsbSerialDataTransfer (
- IN USB_SER_DEV *UsbBot,
- IN EFI_USB_DATA_DIRECTION DataDir,
- IN OUT VOID *Data,
- IN OUT UINTN *TransLen,
- IN UINT32 Timeout
- )
- {
- EFI_USB_ENDPOINT_DESCRIPTOR *Endpoint;
- EFI_STATUS Status;
- UINT32 Result;
- //
- // If no data to transfer, just return EFI_SUCCESS.
- //
- if ((DataDir == EfiUsbNoData) || (*TransLen == 0)) {
- return EFI_SUCCESS;
- }
- //
- // Select the endpoint then issue the transfer
- //
- if (DataDir == EfiUsbDataIn) {
- Endpoint = &UsbBot->InEndpointDescriptor;
- } else {
- Endpoint = &UsbBot->OutEndpointDescriptor;
- }
- Result = 0;
- Status = UsbBot->UsbIo->UsbBulkTransfer (
- UsbBot->UsbIo,
- Endpoint->EndpointAddress,
- Data,
- TransLen,
- Timeout,
- &Result
- );
- if (EFI_ERROR (Status)) {
- if (USB_IS_ERROR (Result, EFI_USB_ERR_NAK)) {
- Status = EFI_NOT_READY;
- } else {
- UsbBot->Shutdown = TRUE; // Fixes infinite loop in older EFI
- }
- return Status;
- }
- return Status;
- }
- /**
- Sets the status values of the Usb Serial Device.
- @param UsbSerialDevice[in] Handle to the Usb Serial Device to set the status
- for
- @param StatusBuffer[in] Buffer holding the status values
- @retval EFI_SUCCESS The status values were read and set correctly
- **/
- EFI_STATUS
- EFIAPI
- SetStatusInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- IN UINT8 *StatusBuffer
- )
- {
- UINT8 Msr;
- Msr = (StatusBuffer[0] & MSR_MASK);
- //
- // set the Status values to disabled
- //
- UsbSerialDevice->StatusValues.CtsState = FALSE;
- UsbSerialDevice->StatusValues.DsrState = FALSE;
- UsbSerialDevice->StatusValues.RiState = FALSE;
- UsbSerialDevice->StatusValues.SdState = FALSE;
- //
- // Check the values from the status buffer and set the appropriate status
- // values to enabled
- //
- if ((Msr & CTS_MASK) == CTS_MASK) {
- UsbSerialDevice->StatusValues.CtsState = TRUE;
- }
- if ((Msr & DSR_MASK) == DSR_MASK) {
- UsbSerialDevice->StatusValues.DsrState = TRUE;
- }
- if ((Msr & RI_MASK) == RI_MASK) {
- UsbSerialDevice->StatusValues.RiState = TRUE;
- }
- if ((Msr & SD_MASK) == SD_MASK) {
- UsbSerialDevice->StatusValues.SdState = TRUE;
- }
- return EFI_SUCCESS;
- }
- /**
- Initiates a read operation on the Usb Serial Device.
- @param UsbSerialDevice[in] Handle to the USB device to read
- @param BufferSize[in, out] On input, the size of the Buffer. On output,
- the amount of data returned in Buffer.
- Setting this to zero will initiate a read
- and store all data returned in the internal
- buffer.
- @param Buffer [out] The buffer to return the data into.
- @retval EFI_SUCCESS The data was read.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_TIMEOUT The data write was stopped due to a timeout.
- **/
- EFI_STATUS
- EFIAPI
- ReadDataFromUsb (
- IN USB_SER_DEV *UsbSerialDevice,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
- {
- EFI_STATUS Status;
- UINTN ReadBufferSize;
- UINT8 *ReadBuffer;
- UINTN Index;
- EFI_TPL Tpl;
- UINT8 StatusBuffer[2]; // buffer to store the status bytes
- ReadBufferSize = 512;
- ReadBuffer = &(UsbSerialDevice->ReadBuffer[0]);
- if (UsbSerialDevice->Shutdown) {
- return EFI_DEVICE_ERROR;
- }
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
- Status = UsbSerialDataTransfer (
- UsbSerialDevice,
- EfiUsbDataIn,
- ReadBuffer,
- &ReadBufferSize,
- FTDI_TIMEOUT*2 //Padded because timers won't be exactly aligned
- );
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- if (Status == EFI_TIMEOUT) {
- return EFI_TIMEOUT;
- } else {
- return EFI_DEVICE_ERROR;
- }
- }
- //
- // Store the status bytes in the status buffer
- //
- for (Index = 0; Index < 2; Index++) {//only the first 2 bytes are status bytes
- StatusBuffer[Index] = ReadBuffer[Index];
- }
- //
- // update the statusvalue field of the usbserialdevice
- //
- Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);
- if (Status != EFI_SUCCESS) {
- }
- //
- // Store the read data in the read buffer, start at 2 to ignore status bytes
- //
- for (Index = 2; Index < ReadBufferSize; Index++) {
- if (((UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH) == UsbSerialDevice->DataBufferHead) {
- break;
- }
- if (ReadBuffer[Index] == 0x00) {
- //
- // This is null, do not add
- //
- } else {
- UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferTail] = ReadBuffer[Index];
- UsbSerialDevice->DataBufferTail = (UsbSerialDevice->DataBufferTail + 1) % SW_FIFO_DEPTH;
- }
- }
- //
- // Read characters out of the buffer to satisfy caller's request.
- //
- for (Index = 0; Index < *BufferSize; Index++) {
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- break;
- }
- //
- // Still have characters in the buffer to return
- //
- ((UINT8 *)Buffer)[Index] = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];
- UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;
- }
- //
- // Return actual number of bytes returned.
- //
- *BufferSize = Index;
- gBS->RestoreTPL (Tpl);
- return EFI_SUCCESS;
- }
- /**
- Sets the initial status values of the Usb Serial Device by reading the status
- bytes from the device.
- @param UsbSerialDevice[in] Handle to the Usb Serial Device that needs its
- initial status values set
- @retval EFI_SUCCESS The status bytes were read successfully and the
- initial status values were set correctly
- @retval EFI_TIMEOUT The read of the status bytes was stopped due to a
- timeout
- @retval EFI_DEVICE_ERROR The device reported an error during the read of
- the status bytes
- **/
- EFI_STATUS
- EFIAPI
- SetInitialStatus (
- IN USB_SER_DEV *UsbSerialDevice
- )
- {
- EFI_STATUS Status;
- UINTN BufferSize;
- EFI_TPL Tpl;
- UINT8 StatusBuffer[2];
- Status = EFI_UNSUPPORTED;
- BufferSize = sizeof (StatusBuffer);
- if (UsbSerialDevice->Shutdown) {
- return EFI_DEVICE_ERROR;
- }
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
- Status = UsbSerialDataTransfer (
- UsbSerialDevice,
- EfiUsbDataIn,
- StatusBuffer,
- &BufferSize,
- 40 //Slightly more than 2x the FTDI polling frequency to make sure that data will be returned
- );
- Status = SetStatusInternal (UsbSerialDevice, StatusBuffer);
- gBS->RestoreTPL (Tpl);
- return Status;
- }
- /**
- UsbSerialDriverCheckInput.
- attempts to read data in from the device periodically, stores any read data
- and updates the control attributes.
- @param Event[in]
- @param Context[in]....The current instance of the USB serial device
- **/
- VOID
- EFIAPI
- UsbSerialDriverCheckInput (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- UINTN BufferSize;
- USB_SER_DEV *UsbSerialDevice;
- UsbSerialDevice = (USB_SER_DEV*)Context;
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- //
- // Data buffer is empty, try to read from device
- //
- BufferSize = 0;
- ReadDataFromUsb (UsbSerialDevice, &BufferSize, NULL);
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- //
- // Data buffer still has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY
- // flag
- //
- UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
- } else {
- //
- // Read has returned some data, clear the EFI_SERIAL_INPUT_BUFFER_EMPTY
- // flag
- //
- UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
- }
- } else {
- //
- // Data buffer has data, no read attempt required
- //
- UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
- }
- }
- /**
- Encodes the baud rate into the format expected by the Ftdi device.
- @param BaudRate[in] The baudrate to be set on the device
- @param EncodedBaudRate[out] The baud rate encoded in the format
- expected by the Ftdi device
- @return EFI_SUCCESS Baudrate encoding was calculated
- successfully
- @return EFI_INVALID_PARAMETER An invalid value of BaudRate was received
- **/
- EFI_STATUS
- EFIAPI
- EncodeBaudRateForFtdi (
- IN UINT64 BaudRate,
- OUT UINT16 *EncodedBaudRate
- )
- {
- UINT32 Divisor;
- UINT32 AdjustedFrequency;
- UINT16 Result;
- //
- // Check to make sure we won't get an integer overflow
- //
- if ((BaudRate < 178) || ( BaudRate > ((FTDI_UART_FREQUENCY * 100) / 97))) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Baud Rates of 2000000 and 3000000 are special cases
- //
- if ((BaudRate >= FTDI_SPECIAL_CASE_300_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_300_MAX)) {
- *EncodedBaudRate = 0;
- return EFI_SUCCESS;
- }
- if ((BaudRate >= FTDI_SPECIAL_CASE_200_MIN) && (BaudRate <= FTDI_SPECIAL_CASE_200_MAX)) {
- *EncodedBaudRate = 1;
- return EFI_SUCCESS;
- }
- //
- // Compute divisor
- //
- Divisor = (FTDI_UART_FREQUENCY << 4) / (UINT32)BaudRate;
- //
- // Round the last 4 bits to the nearest power of 2
- //
- Divisor = (Divisor & ~(0xF)) + (gRoundedPowersOf2[Divisor & 0xF]);
- //
- // Check to make sure computed divisor is within
- // the min and max that FTDI controller will accept
- //
- if (Divisor < FTDI_MIN_DIVISOR) {
- Divisor = FTDI_MIN_DIVISOR;
- } else if (Divisor > FTDI_MAX_DIVISOR) {
- Divisor = FTDI_MAX_DIVISOR;
- }
- //
- // Check to make sure the frequency that the FTDI chip will need to
- // generate to attain the requested Baud Rate is within 3% of the
- // 3MHz clock frequency that the FTDI chip runs at.
- //
- // (3MHz * 1600) / 103 = 46601941
- // (3MHz * 1600) / 97 = 49484536
- //
- AdjustedFrequency = (((UINT32)BaudRate) * Divisor);
- if ((AdjustedFrequency < FTDI_MIN_FREQUENCY) || (AdjustedFrequency > FTDI_MAX_FREQUENCY)) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Encode the Divisor into the format FTDI expects
- //
- Result = (UINT16)(Divisor >> 4);
- if ((Divisor & 0x8) != 0) {
- Result |= 0x4000;
- } else if ((Divisor & 0x4) != 0) {
- Result |= 0x8000;
- } else if ((Divisor & 0x2) != 0) {
- Result |= 0xC000;
- }
- *EncodedBaudRate = Result;
- return EFI_SUCCESS;
- }
- /**
- Uses USB I/O to check whether the device is a USB Serial device.
- @param UsbIo[in] Pointer to a USB I/O protocol instance.
- @retval TRUE Device is a USB Serial device.
- @retval FALSE Device is a not USB Serial device.
- **/
- BOOLEAN
- IsUsbSerial (
- IN EFI_USB_IO_PROTOCOL *UsbIo
- )
- {
- EFI_STATUS Status;
- EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
- CHAR16 *StrMfg;
- BOOLEAN Found;
- UINT32 Index;
- //
- // Get the default device descriptor
- //
- Status = UsbIo->UsbGetDeviceDescriptor (
- UsbIo,
- &DeviceDescriptor
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- Found = FALSE;
- Index = 0;
- while (gUSBDeviceList[Index].VendorId != 0 &&
- gUSBDeviceList[Index].DeviceId != 0 &&
- !Found ) {
- if (DeviceDescriptor.IdProduct == gUSBDeviceList[Index].DeviceId &&
- DeviceDescriptor.IdVendor == gUSBDeviceList[Index].VendorId ){
- //
- // Checks to see if a string descriptor can be pulled from the device in
- // the selected language. If not False is returned indicating that this
- // is not a Usb Serial Device that can be managegd by this driver
- //
- StrMfg = NULL;
- Status = UsbIo->UsbGetStringDescriptor (
- UsbIo,
- USB_US_LANG_ID, // LANGID selector, should make this
- // more robust to verify lang support
- // for device
- DeviceDescriptor.StrManufacturer,
- &StrMfg
- );
- if (StrMfg != NULL) {
- FreePool (StrMfg);
- }
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- return TRUE;
- }
- Index++;
- }
- return FALSE;
- }
- /**
- Internal function that sets the Data Bits, Stop Bits and Parity values on the
- Usb Serial Device with a single usb control transfer.
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param DataBits[in] The data bits value to be set on the Usb
- Serial Device
- @param Parity[in] The parity type that will be set on the Usb
- Serial Device
- @param StopBits[in] The stop bits type that will be set on the
- Usb Serial Device
- @param LastSettings[in] A pointer to the Usb Serial Device's
- PREVIOUS_ATTRIBUTES item
- @retval EFI_SUCCESS The data items were correctly set on the
- USB Serial Device
- @retval EFI_INVALID_PARAMETER An invalid data parameter or an invalid
- combination or parameters was used
- @retval EFI_DEVICE_ERROR The device is not functioning correctly and
- the data values were unable to be set
- **/
- EFI_STATUS
- EFIAPI
- SetDataInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN UINT8 DataBits,
- IN EFI_PARITY_TYPE Parity,
- IN EFI_STOP_BITS_TYPE StopBits,
- IN PREVIOUS_ATTRIBUTES *LastSettings
- )
- {
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
- //
- // Since data bits settings of 6,7,8 cannot be set with a stop bits setting of
- // 1.5 check to see if this happens when the values of last settings are used
- //
- if ((DataBits == 0) && (StopBits == OneFiveStopBits)) {
- if ((LastSettings->DataBits == 6) || (LastSettings->DataBits == 7) || (LastSettings->DataBits == 8)) {
- return EFI_INVALID_PARAMETER;
- }
- } else if ((StopBits == DefaultStopBits) && ((DataBits == 6) || (DataBits == 7) || (DataBits == 8))) {
- if (LastSettings->StopBits == OneFiveStopBits) {
- return EFI_INVALID_PARAMETER;
- }
- } else if ((DataBits == 0) && (StopBits == DefaultStopBits)) {
- if (LastSettings->StopBits == OneFiveStopBits) {
- if ((LastSettings->DataBits == 6) || (LastSettings->DataBits == 7) || (LastSettings->DataBits == 8)) {
- return EFI_INVALID_PARAMETER;
- }
- }
- }
- //
- // set the DevReq.Value for the usb control transfer to the correct value
- // based on the seleceted number of data bits if there is an invalid number of
- // data bits requested return EFI_INVALID_PARAMETER
- //
- if (((DataBits < 5 ) || (DataBits > 8)) && (DataBits != 0)) {
- return EFI_INVALID_PARAMETER;
- }
- if (DataBits == 0) {
- //
- // use the value of LastDataBits
- //
- DevReq.Value = SET_DATA_BITS (LastSettings->DataBits);
- } else {
- //
- // use the value of DataBits
- //
- DevReq.Value = SET_DATA_BITS (DataBits);
- }
- //
- // Set Parity
- //
- if (Parity == DefaultParity) {
- Parity = LastSettings->Parity;
- }
- if (Parity == NoParity) {
- DevReq.Value |= SET_PARITY_NONE;
- } else if (Parity == EvenParity) {
- DevReq.Value |= SET_PARITY_EVEN;
- } else if (Parity == OddParity){
- DevReq.Value |= SET_PARITY_ODD;
- } else if (Parity == MarkParity) {
- DevReq.Value |= SET_PARITY_MARK;
- } else if (Parity == SpaceParity) {
- DevReq.Value |= SET_PARITY_SPACE;
- }
- //
- // Set Stop Bits
- //
- if (StopBits == DefaultStopBits) {
- StopBits = LastSettings->StopBits;
- }
- if (StopBits == OneStopBit) {
- DevReq.Value |= SET_STOP_BITS_1;
- } else if (StopBits == OneFiveStopBits) {
- DevReq.Value |= SET_STOP_BITS_15;
- } else if (StopBits == TwoStopBits) {
- DevReq.Value |= SET_STOP_BITS_2;
- }
- //
- // set the rest of the DevReq parameters and perform the usb control transfer
- // to set the data bits on the device
- //
- DevReq.Request = FTDI_COMMAND_SET_DATA;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this request
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_SHORT_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- return Status;
- StatusError:
- if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
- }
- /**
- Internal function that sets the baudrate on the Usb Serial Device.
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param BaudRate[in] The baudrate value to be set on the device.
- If this value is 0 the value of LastBaudRate
- will be used instead
- @param LastBaudRate[in] The baud rate value that was previously set
- on the Usb Serial Device
- @retval EFI_SUCCESS The baudrate was set succesfully
- @retval EFI_INVALID_PARAMETER An invalid baudrate was used
- @retval EFI_DEVICE_ERROR The device is not functioning correctly and
- the baudrate was unable to be set
- **/
- EFI_STATUS
- EFIAPI
- SetBaudRateInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN UINT64 BaudRate,
- IN UINT64 LastBaudRate
- )
- {
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
- UINT16 EncodedBaudRate;
- EFI_TPL Tpl;
- Tpl = gBS->RaiseTPL(TPL_NOTIFY);
- //
- // set the value of DevReq.Value based on the value of BaudRate
- // if 0 is selected as baud rate use the value of LastBaudRate
- //
- if (BaudRate == 0) {
- Status = EncodeBaudRateForFtdi (LastBaudRate, &EncodedBaudRate);
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- //
- // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
- // succesfull
- //
- return Status;
- }
- DevReq.Value = EncodedBaudRate;
- } else {
- Status = EncodeBaudRateForFtdi (BaudRate, &EncodedBaudRate);
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (Tpl);
- //
- // EncodeBaudRateForFtdi returns EFI_INVALID_PARAMETER when not
- // successfull
- //
- return Status;
- }
- DevReq.Value = EncodedBaudRate;
- }
- //
- // set the remaining parameters of DevReq and perform the usb control transfer
- // to set the device
- //
- DevReq.Request = FTDI_COMMAND_SET_BAUDRATE;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this request
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_SHORT_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- gBS->RestoreTPL (Tpl);
- return Status;
- StatusError:
- gBS->RestoreTPL (Tpl);
- if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
- }
- /**
- Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
- data bits, and stop bits on a serial device.
- @param UsbSerialDevice[in] Pointer to the current instance of the USB Serial
- Device.
- @param BaudRate[in] The requested baud rate. A BaudRate value of 0
- will use the device's default interface speed.
- @param ReveiveFifoDepth[in] The requested depth of the FIFO on the receive
- side of the serial interface. A ReceiveFifoDepth
- value of 0 will use the device's default FIFO
- depth.
- @param Timeout[in] The requested time out for a single character in
- microseconds.This timeout applies to both the
- transmit and receive side of the interface.A
- Timeout value of 0 will use the device's default
- time out value.
- @param Parity[in] The type of parity to use on this serial device.
- A Parity value of DefaultParity will use the
- device's default parity value.
- @param DataBits[in] The number of data bits to use on the serial
- device. A DataBits value of 0 will use the
- device's default data bit setting.
- @param StopBits[in] The number of stop bits to use on this serial
- device. A StopBits value of DefaultStopBits will
- use the device's default number of stop bits.
- @retval EFI_SUCCESS The attributes were set
- @retval EFI_DEVICE_ERROR The attributes were not able to be set
- **/
- EFI_STATUS
- EFIAPI
- SetAttributesInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- IN UINT64 BaudRate,
- IN UINT32 ReceiveFifoDepth,
- IN UINT32 Timeout,
- IN EFI_PARITY_TYPE Parity,
- IN UINT8 DataBits,
- IN EFI_STOP_BITS_TYPE StopBits
- )
- {
- EFI_STATUS Status;
- EFI_TPL Tpl;
- UART_DEVICE_PATH *Uart;
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
- Status = EFI_UNSUPPORTED;
- Tpl = gBS->RaiseTPL(TPL_NOTIFY);
- Uart = NULL;
- //
- // check for invalid combinations of parameters
- //
- if (((DataBits >= 6) && (DataBits <= 8)) && (StopBits == OneFiveStopBits)) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // set data bits, parity and stop bits
- //
- Status = SetDataInternal (
- UsbSerialDevice->UsbIo,
- DataBits,
- Parity,
- StopBits,
- &(UsbSerialDevice->LastSettings)
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- //
- // set baudrate
- //
- Status = SetBaudRateInternal (
- UsbSerialDevice->UsbIo,
- BaudRate,
- UsbSerialDevice->LastSettings.BaudRate
- );
- if (EFI_ERROR (Status)){
- goto StatusError;
- }
- //
- // update the values of UsbSerialDevice->LastSettings and UsbSerialDevice->SerialIo.Mode
- //
- if (BaudRate == 0) {
- UsbSerialDevice->LastSettings.BaudRate = UsbSerialDevice->LastSettings.BaudRate;
- UsbSerialDevice->SerialIo.Mode->BaudRate = UsbSerialDevice->LastSettings.BaudRate;
- } else {
- UsbSerialDevice->LastSettings.BaudRate = BaudRate;
- UsbSerialDevice->SerialIo.Mode->BaudRate = BaudRate;
- }
- UsbSerialDevice->LastSettings.Timeout = FTDI_TIMEOUT;
- UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;
- if (Parity == DefaultParity) {
- UsbSerialDevice->LastSettings.Parity = UsbSerialDevice->LastSettings.Parity;
- UsbSerialDevice->SerialIo.Mode->Parity = UsbSerialDevice->LastSettings.Parity;
- } else {
- UsbSerialDevice->LastSettings.Parity = Parity;
- UsbSerialDevice->SerialIo.Mode->Parity = Parity;
- }
- if (DataBits == 0) {
- UsbSerialDevice->LastSettings.DataBits = UsbSerialDevice->LastSettings.DataBits;
- UsbSerialDevice->SerialIo.Mode->DataBits = UsbSerialDevice->LastSettings.DataBits;
- } else {
- UsbSerialDevice->LastSettings.DataBits = DataBits;
- UsbSerialDevice->SerialIo.Mode->DataBits = DataBits;
- }
- if (StopBits == DefaultStopBits) {
- UsbSerialDevice->LastSettings.StopBits = UsbSerialDevice->LastSettings.StopBits;
- UsbSerialDevice->SerialIo.Mode->StopBits = UsbSerialDevice->LastSettings.StopBits;
- } else {
- UsbSerialDevice->LastSettings.StopBits = StopBits;
- UsbSerialDevice->SerialIo.Mode->StopBits = StopBits;
- }
- //
- // See if the device path node has changed
- //
- if (UsbSerialDevice->UartDevicePath.BaudRate == BaudRate &&
- UsbSerialDevice->UartDevicePath.DataBits == DataBits &&
- UsbSerialDevice->UartDevicePath.StopBits == StopBits &&
- UsbSerialDevice->UartDevicePath.Parity == Parity
- ) {
- gBS->RestoreTPL (Tpl);
- return EFI_SUCCESS;
- }
- //
- // Update the device path
- //
- UsbSerialDevice->UartDevicePath.BaudRate = BaudRate;
- UsbSerialDevice->UartDevicePath.DataBits = DataBits;
- UsbSerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
- UsbSerialDevice->UartDevicePath.Parity = (UINT8) Parity;
- Status = EFI_SUCCESS;
- if (UsbSerialDevice->ControllerHandle != NULL) {
- RemainingDevicePath = UsbSerialDevice->DevicePath;
- while (!IsDevicePathEnd (RemainingDevicePath)) {
- Uart = (UART_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (Uart->Header.Type == MESSAGING_DEVICE_PATH &&
- Uart->Header.SubType == MSG_UART_DP &&
- sizeof (UART_DEVICE_PATH) == DevicePathNodeLength ((EFI_DEVICE_PATH *) Uart)) {
- Uart->BaudRate = BaudRate;
- Uart->DataBits = DataBits;
- Uart->StopBits = (UINT8)StopBits;
- Uart->Parity = (UINT8) Parity;
- break;
- }
- RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
- }
- }
- gBS->RestoreTPL (Tpl);
- return Status;
- StatusError:
- gBS->RestoreTPL (Tpl);
- if ((Status != EFI_INVALID_PARAMETER) || (Status != EFI_DEVICE_ERROR)) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
- }
- /**
- Internal function that performs a Usb Control Transfer to set the flow control
- on the Usb Serial Device.
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param FlowControlEnable[in] Data on the Enable/Disable status of Flow
- Control on the Usb Serial Device
- @retval EFI_SUCCESS The flow control was set on the Usb Serial
- device
- @retval EFI_INVALID_PARAMETER An invalid flow control value was used
- @retval EFI_EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
- **/
- EFI_STATUS
- EFIAPI
- SetFlowControlInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN BOOLEAN FlowControlEnable
- )
- {
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
- //
- // set DevReq.Value based on the value of FlowControlEnable
- //
- if (!FlowControlEnable) {
- DevReq.Value = NO_FLOW_CTRL;
- }
- if (FlowControlEnable) {
- DevReq.Value = XON_XOFF_CTRL;
- }
- //
- // set the remaining DevReq parameters and perform the usb control transfer to
- // set the flow control on the device
- //
- DevReq.Request = FTDI_COMMAND_SET_FLOW_CTRL;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that this transfer has no data phase
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- return Status;
- StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
- }
- /**
- Internal function that performs a Usb Control Transfer to set the Dtr value on
- the Usb Serial Device.
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param DtrEnable[in] Data on the Enable/Disable status of the
- Dtr for the Usb Serial Device
- @retval EFI_SUCCESS The Dtr value was set on the Usb Serial
- Device
- @retval EFI_INVALID_PARAMETER An invalid Dtr value was used
- @retval EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
- **/
- EFI_STATUS
- EFIAPI
- SetDtrInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN BOOLEAN DtrEnable
- )
- {
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
- //
- // set the value of DevReq.Value based on the value of DtrEnable
- //
- if (!DtrEnable) {
- DevReq.Value = SET_DTR_LOW;
- }
- if (DtrEnable) {
- DevReq.Value = SET_DTR_HIGH;
- }
- //
- // set the remaining attributes of DevReq and perform the usb control transfer
- // to set the device
- //
- DevReq.Request = FTDI_COMMAND_MODEM_CTRL;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this transfer
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- return Status;
- StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
- }
- /**
- Internal function that performs a Usb Control Transfer to set the Dtr value on
- the Usb Serial Device.
-
- @param UsbIo[in] Usb Io Protocol instance pointer
- @param RtsEnable[in] Data on the Enable/Disable status of the
- Rts for the Usb Serial Device
- @retval EFI_SUCCESS The Rts value was set on the Usb Serial
- Device
- @retval EFI_INVALID_PARAMETER An invalid Rts value was used
- @retval EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
- **/
- EFI_STATUS
- EFIAPI
- SetRtsInternal (
- IN EFI_USB_IO_PROTOCOL *UsbIo,
- IN BOOLEAN RtsEnable
- )
- {
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT32 ReturnValue;
- UINT8 ConfigurationValue;
- //
- // set DevReq.Value based on the value of RtsEnable
- //
- if (!RtsEnable) {
- DevReq.Value = SET_RTS_LOW;
- }
- if (RtsEnable) {
- DevReq.Value = SET_RTS_HIGH;
- }
- //
- // set the remaining parameters of DevReq and perform the usb control transfer
- // to set the values on the device
- //
- DevReq.Request = FTDI_COMMAND_MODEM_CTRL;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; // indicates that there is no data phase in this request
- Status = UsbIo->UsbControlTransfer (
- UsbIo,
- &DevReq,
- EfiUsbDataOut,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- return Status;
- StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
- }
- /**
- Internal function that checks for valid control values and sets the control
- bits on the Usb Serial Device.
- @param UsbSerialDevice[in] Handle to the Usb Serial Device whose
- control bits are being set
- @param Control[in] The control value passed to the function
- that contains the values of the control
- bits that are being set
- @retval EFI_SUCCESS The control bits were set on the Usb Serial
- Device
- @retval EFI_INVALID_PARAMETER An invalid control value was encountered
- @retval EFI_EFI_UNSUPPORTED The operation is not supported
- @retval EFI_DEVICE_ERROR The device is not functioning correctly
- **/
- EFI_STATUS
- EFIAPI
- SetControlBitsInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- IN CONTROL_BITS *Control
- )
- {
- EFI_STATUS Status;
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
- //
- // check for invalid control parameters hardware and software loopback enabled
- // must always be set to FALSE
- //
- Control->HardwareLoopBack = FALSE;
- Control->SoftwareLoopBack = FALSE;
- //
- // set hardware flow control
- //
- Status = SetFlowControlInternal (
- UsbSerialDevice->UsbIo,
- Control->HardwareFlowControl
- );
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- //
- // set Dtr state
- //
- Status = SetDtrInternal (UsbSerialDevice->UsbIo, Control->DtrState);
- if (EFI_ERROR (Status)) {
- goto StatusError;
- }
- //
- // set Rts state
- //
- Status = SetRtsInternal (UsbSerialDevice->UsbIo, Control->RtsState);
- if (EFI_ERROR (Status)){
- goto StatusError;
- }
- //
- // update the remaining control values for UsbSerialDevice->ControlValues
- //
- UsbSerialDevice->ControlValues.DtrState = Control->DtrState;
- UsbSerialDevice->ControlValues.RtsState = Control->RtsState;
- UsbSerialDevice->ControlValues.HardwareFlowControl = Control->HardwareFlowControl;
- UsbSerialDevice->ControlValues.HardwareLoopBack = FALSE;
- UsbSerialDevice->ControlValues.SoftwareLoopBack = FALSE;
- Status = EFI_SUCCESS;
- //
- // Update the device path to have the correct flow control values
- //
- if (UsbSerialDevice->ControllerHandle != NULL) {
- RemainingDevicePath = UsbSerialDevice->DevicePath;
- while (!IsDevicePathEnd (RemainingDevicePath)) {
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (FlowControl->Header.Type == MESSAGING_DEVICE_PATH &&
- FlowControl->Header.SubType == MSG_VENDOR_DP &&
- sizeof (UART_FLOW_CONTROL_DEVICE_PATH) == DevicePathNodeLength ((EFI_DEVICE_PATH *) FlowControl)){
- if (UsbSerialDevice->ControlValues.HardwareFlowControl == TRUE) {
- FlowControl->FlowControlMap = UART_FLOW_CONTROL_HARDWARE;
- } else if (UsbSerialDevice->ControlValues.HardwareFlowControl == FALSE) {
- FlowControl->FlowControlMap = 0;
- }
- break;
- }
- RemainingDevicePath = NextDevicePathNode (RemainingDevicePath);
- }
- }
- return Status;
- StatusError:
- if ((Status != EFI_INVALID_PARAMETER) ||
- (Status != EFI_DEVICE_ERROR) ||
- (Status != EFI_UNSUPPORTED) ) {
- return EFI_DEVICE_ERROR;
- } else {
- return Status;
- }
- }
- /**
- Internal function that calculates the Control value used by GetControlBits()
- based on the status and control values of the Usb Serial Device.
- @param UsbSerialDevice[in] Handle to the Usb Serial Devie whose status
- and control values are being used to set
- Control
- @param Control[out] On output the formated value of Control
- that has been calculated based on the
- control and status values of the Usb Serial
- Device
- @retval EFI_SUCCESS The value of Control was successfully
- calculated
- **/
- EFI_STATUS
- EFIAPI
- GetControlBitsInternal (
- IN USB_SER_DEV *UsbSerialDevice,
- OUT UINT32 *Control
- )
- {
- *Control = 0;
- //
- // Check the values of UsbSerialDevice->Status Values and modify control
- // accordingly these values correspond to the modem status register
- //
- if (UsbSerialDevice->StatusValues.CtsState) {
- *Control |= EFI_SERIAL_CLEAR_TO_SEND;
- }
- if (UsbSerialDevice->StatusValues.DsrState) {
- *Control |= EFI_SERIAL_DATA_SET_READY;
- }
- if (UsbSerialDevice->StatusValues.RiState) {
- *Control |= EFI_SERIAL_RING_INDICATE;
- }
- if (UsbSerialDevice->StatusValues.SdState) {
- *Control |= EFI_SERIAL_CARRIER_DETECT;
- }
- //
- // check the values of UsbSerialDevice->ControlValues and modify control
- // accordingly these values correspond to the values of the Modem Control
- // Register
- //
- if (UsbSerialDevice->ControlValues.DtrState) {
- *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
- }
- if (UsbSerialDevice->ControlValues.RtsState) {
- *Control |= EFI_SERIAL_REQUEST_TO_SEND;
- }
- if (UsbSerialDevice->ControlValues.HardwareLoopBack) {
- *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
- }
- if (UsbSerialDevice->ControlValues.HardwareFlowControl) {
- *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
- //
- // check if the buffer is empty since only one is being used if it is empty
- // set both the receive and transmit buffers to empty
- //
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
- *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
- }
- //
- // check for software loopback enable in UsbSerialDevice->ControlValues
- //
- if (UsbSerialDevice->ControlValues.SoftwareLoopBack) {
- *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
- }
- return EFI_SUCCESS;
- }
- /**
- Resets the USB Serial Device
- This function is the internal method for resetting the device and is called by
- SerialReset()
- @param UsbSerialDevice[in] A pointer to the USB Serial device
- @retval EFI_SUCCESS The device was reset
- @retval EFI_DEVICE_ERROR The device could not be reset
- **/
- EFI_STATUS
- EFIAPI
- ResetInternal (
- IN USB_SER_DEV *UsbSerialDevice
- )
- {
- EFI_STATUS Status;
- EFI_USB_DEVICE_REQUEST DevReq;
- UINT8 ConfigurationValue;
- UINT32 ReturnValue;
- DevReq.Request = FTDI_COMMAND_RESET_PORT;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Value = RESET_PORT_PURGE_RX;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; //indicates that there is not data phase in this request
- Status = UsbSerialDevice->UsbIo->UsbControlTransfer (
- UsbSerialDevice->UsbIo,
- &DevReq,
- EfiUsbDataIn,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- DevReq.Request = FTDI_COMMAND_RESET_PORT;
- DevReq.RequestType = USB_REQ_TYPE_VENDOR;
- DevReq.Value = RESET_PORT_PURGE_TX;
- DevReq.Index = FTDI_PORT_IDENTIFIER;
- DevReq.Length = 0; //indicates that there is no data phase in this request
- Status = UsbSerialDevice->UsbIo->UsbControlTransfer (
- UsbSerialDevice->UsbIo,
- &DevReq,
- EfiUsbDataIn,
- WDR_TIMEOUT,
- &ConfigurationValue,
- 1,
- &ReturnValue
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- return Status;
- }
- /**
- Entrypoint of USB Serial Driver.
- This function is the entrypoint of USB Serial Driver. It installs
- Driver Binding Protocols together with Component Name Protocols.
- @param ImageHandle[in] The firmware allocated handle for the EFI image.
- @param SystemTable[in] A pointer to the EFI System Table.
- @retval EFI_SUCCESS The entry point is executed successfully.
- **/
- EFI_STATUS
- EFIAPI
- FtdiUsbSerialEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gUsbSerialDriverBinding,
- ImageHandle,
- &gUsbSerialComponentName,
- &gUsbSerialComponentName2
- );
- ASSERT_EFI_ERROR (Status);
- return EFI_SUCCESS;
- }
- /**
- Unload function for the Usb Serial Driver.
- @param ImageHandle[in] The allocated handle for the EFI image
- @retval EFI_SUCCESS The driver was unloaded successfully
- **/
- EFI_STATUS
- EFIAPI
- FtdiUsbSerialUnload (
- IN EFI_HANDLE ImageHandle
- )
- {
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
- //
- // Retrieve all handles in the handle database
- //
- Status = gBS->LocateHandleBuffer (
- AllHandles,
- NULL,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Disconnect the driver from the handles in the handle database
- //
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->DisconnectController (
- HandleBuffer[Index],
- gImageHandle,
- NULL
- );
- }
- //
- // Free the handle array
- //
- FreePool (HandleBuffer);
- //
- // Uninstall protocols installed by the driver in its entrypoint
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ImageHandle,
- &gEfiDriverBindingProtocolGuid,
- &gUsbSerialDriverBinding,
- &gEfiComponentNameProtocolGuid,
- &gUsbSerialComponentName,
- &gEfiComponentName2ProtocolGuid,
- &gUsbSerialComponentName2,
- NULL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- return EFI_SUCCESS;
- }
- /**
- Check whether USB Serial driver supports this device.
- @param This[in] The USB Serial driver binding protocol.
- @param Controller[in] The controller handle to check.
- @param RemainingDevicePath[in] The remaining device path.
- @retval EFI_SUCCESS The driver supports this controller.
- @retval other This device isn't supported.
- **/
- EFI_STATUS
- EFIAPI
- UsbSerialDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_STATUS Status;
- EFI_USB_IO_PROTOCOL *UsbIo;
- UART_DEVICE_PATH *UartNode;
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode;
- UINTN Index;
- UINTN EntryCount;
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
- BOOLEAN HasFlowControl;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
- if (RemainingDevicePath != NULL) {
- if (!IsDevicePathEnd (RemainingDevicePath)) {
- Status = EFI_UNSUPPORTED;
- UartNode = (UART_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (UartNode->Header.Type != MESSAGING_DEVICE_PATH ||
- UartNode->Header.SubType != MSG_UART_DP ||
- sizeof (UART_DEVICE_PATH) != DevicePathNodeLength ((EFI_DEVICE_PATH *) UartNode)) {
- goto Error;
- }
- FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (UartNode);
- if ((ReadUnaligned32 (&FlowControlNode->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) {
- goto Error;
- }
- }
- }
- //
- // Check if USB I/O Protocol is attached on the controller handle.
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (Status == EFI_ALREADY_STARTED) {
- if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
- return EFI_SUCCESS;
- }
- Status = gBS->OpenProtocolInformation (
- Controller,
- &gEfiUsbIoProtocolGuid,
- &OpenInfoBuffer,
- &EntryCount
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- for (Index = 0; Index < EntryCount; Index++) {
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- Status = gBS->OpenProtocol (
- OpenInfoBuffer[Index].ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &DevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- HasFlowControl = ContainsFlowControl (RemainingDevicePath);
- if (HasFlowControl ^ ContainsFlowControl (DevicePath)) {
- Status = EFI_UNSUPPORTED;
- }
- }
- break;
- }
- }
- FreePool (OpenInfoBuffer);
- return Status;
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ParentDevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (Status == EFI_ALREADY_STARTED) {
- return EFI_SUCCESS;
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Use the USB I/O Protocol interface to check whether Controller is
- // a USB Serial device that can be managed by this driver.
- //
- Status = EFI_SUCCESS;
- if (!IsUsbSerial (UsbIo)) {
- Status = EFI_UNSUPPORTED;
- goto Error;
- }
- Error:
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- return Status;
- }
- /**
- Starts the USB Serial device with this driver.
- This function produces initializes the USB Serial device and
- produces the Serial IO Protocol.
- @param This[in] The USB Serial driver binding instance.
- @param Controller[in] Handle of device to bind driver to.
- @param RemainingDevicePath[in] Optional parameter use to pick a specific
- child device to start.
- @retval EFI_SUCCESS The controller is controlled by the usb USB
- Serial driver.
- @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
- @retval Other This controller cannot be started.
- **/
- EFI_STATUS
- EFIAPI
- UsbSerialDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_STATUS Status;
- EFI_USB_IO_PROTOCOL *UsbIo;
- USB_SER_DEV *UsbSerialDevice;
- UINT8 EndpointNumber;
- EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
- UINT8 Index;
- BOOLEAN FoundIn;
- BOOLEAN FoundOut;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
- UINTN EntryCount;
- EFI_SERIAL_IO_PROTOCOL *SerialIo;
- UART_DEVICE_PATH *Uart;
- UART_FLOW_CONTROL_DEVICE_PATH *FlowControl;
- UINT32 Control;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
- UsbSerialDevice = AllocateZeroPool (sizeof (USB_SER_DEV));
- ASSERT (UsbSerialDevice != NULL);
- //
- // Get the Parent Device path
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ParentDevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
- goto ErrorExit1;
- }
- //
- // Open USB I/O Protocol
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
- goto ErrorExit1;
- }
- if (Status == EFI_ALREADY_STARTED) {
- if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) {
- FreePool (UsbSerialDevice);
- return EFI_SUCCESS;
- }
- //
- // Check to see if a child handle exists
- //
- Status = gBS->OpenProtocolInformation (
- Controller,
- &gEfiSerialIoProtocolGuid,
- &OpenInfoBuffer,
- &EntryCount
- );
- if (EFI_ERROR (Status)) {
- goto ErrorExit1;
- }
- Status = EFI_ALREADY_STARTED;
- for (Index = 0; Index < EntryCount; Index++) {
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- Status = gBS->OpenProtocol (
- OpenInfoBuffer[Index].ControllerHandle,
- &gEfiSerialIoProtocolGuid,
- (VOID **) &SerialIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- }
- if (!EFI_ERROR (Status)) {
- Uart = (UART_DEVICE_PATH *) RemainingDevicePath;
- Status = SerialIo->SetAttributes (
- SerialIo,
- Uart->BaudRate,
- SerialIo->Mode->ReceiveFifoDepth,
- SerialIo->Mode->Timeout,
- (EFI_PARITY_TYPE) Uart->Parity,
- Uart->DataBits,
- (EFI_STOP_BITS_TYPE) Uart->StopBits
- );
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart);
- if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) {
- Status = SerialIo->GetControl (
- SerialIo,
- &Control
- );
- if (!EFI_ERROR (Status)) {
- if (ReadUnaligned32 (&FlowControl->FlowControlMap) == UART_FLOW_CONTROL_HARDWARE) {
- Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- } else {
- Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
- //
- // Clear bits that are not allowed to be passed to SetControl
- //
- Control &= (EFI_SERIAL_REQUEST_TO_SEND |
- EFI_SERIAL_DATA_TERMINAL_READY |
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE);
- Status = SerialIo->SetControl (SerialIo, Control);
- }
- }
- }
- break;
- }
- }
- FreePool (OpenInfoBuffer);
- return Status;
- }
- if (RemainingDevicePath != NULL) {
- if (IsDevicePathEnd (RemainingDevicePath)) {
- return EFI_SUCCESS;
- }
- }
- UsbSerialDevice->UsbIo = UsbIo;
- //
- // Get interface & endpoint descriptor
- //
- UsbIo->UsbGetInterfaceDescriptor (
- UsbIo,
- &UsbSerialDevice->InterfaceDescriptor
- );
- EndpointNumber = UsbSerialDevice->InterfaceDescriptor.NumEndpoints;
- //
- // Traverse endpoints to find the IN and OUT endpoints that will send and
- // receive data.
- //
- FoundIn = FALSE;
- FoundOut = FALSE;
- for (Index = 0; Index < EndpointNumber; Index++) {
- Status = UsbIo->UsbGetEndpointDescriptor (
- UsbIo,
- Index,
- &EndpointDescriptor
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_OUT) {
- //
- // Set the Out endpoint device
- //
- CopyMem (
- &UsbSerialDevice->OutEndpointDescriptor,
- &EndpointDescriptor,
- sizeof(EndpointDescriptor)
- );
- FoundOut = TRUE;
- }
- if (EndpointDescriptor.EndpointAddress == FTDI_ENDPOINT_ADDRESS_IN) {
- //
- // Set the In endpoint device
- //
- CopyMem (
- &UsbSerialDevice->InEndpointDescriptor,
- &EndpointDescriptor,
- sizeof(EndpointDescriptor)
- );
- FoundIn = TRUE;
- }
- }
- if (!FoundIn || !FoundOut) {
- //
- // No interrupt endpoint found, then return unsupported.
- //
- Status = EFI_UNSUPPORTED;
- goto ErrorExit;
- }
- //
- // set the initial values of UsbSerialDevice->LastSettings to the default
- // values
- //
- UsbSerialDevice->LastSettings.BaudRate = 115200;
- UsbSerialDevice->LastSettings.DataBits = 8;
- UsbSerialDevice->LastSettings.Parity = NoParity;
- UsbSerialDevice->LastSettings.ReceiveFifoDepth = FTDI_MAX_RECEIVE_FIFO_DEPTH;
- UsbSerialDevice->LastSettings.StopBits = OneStopBit;
- UsbSerialDevice->LastSettings.Timeout = FTDI_TIMEOUT;
- //
- // set the initial values of UsbSerialDevice->ControlValues
- //
- UsbSerialDevice->ControlValues.DtrState = FALSE;
- UsbSerialDevice->ControlValues.RtsState = FALSE;
- UsbSerialDevice->ControlValues.HardwareFlowControl = FALSE;
- UsbSerialDevice->ControlValues.HardwareLoopBack = FALSE;
- UsbSerialDevice->ControlValues.SoftwareLoopBack = FALSE;
- //
- // set the values of UsbSerialDevice->UartDevicePath
- //
- UsbSerialDevice->UartDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
- UsbSerialDevice->UartDevicePath.Header.SubType = MSG_UART_DP;
- UsbSerialDevice->UartDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_DEVICE_PATH));
- UsbSerialDevice->UartDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8);
- //
- // set the values of UsbSerialDevice->FlowControlDevicePath
- UsbSerialDevice->FlowControlDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
- UsbSerialDevice->FlowControlDevicePath.Header.SubType = MSG_VENDOR_DP;
- UsbSerialDevice->FlowControlDevicePath.Header.Length[0] = (UINT8) (sizeof (UART_FLOW_CONTROL_DEVICE_PATH));
- UsbSerialDevice->FlowControlDevicePath.Header.Length[1] = (UINT8) ((sizeof (UART_FLOW_CONTROL_DEVICE_PATH)) >> 8);
- UsbSerialDevice->FlowControlDevicePath.FlowControlMap = 0;
- Status = SetAttributesInternal (
- UsbSerialDevice,
- UsbSerialDevice->LastSettings.BaudRate,
- UsbSerialDevice->LastSettings.ReceiveFifoDepth,
- UsbSerialDevice->LastSettings.Timeout,
- UsbSerialDevice->LastSettings.Parity,
- UsbSerialDevice->LastSettings.DataBits,
- UsbSerialDevice->LastSettings.StopBits
- );
- ASSERT_EFI_ERROR (Status);
- Status = SetControlBitsInternal (
- UsbSerialDevice,
- &(UsbSerialDevice->ControlValues)
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Publish Serial GUID and protocol
- //
- UsbSerialDevice->Signature = USB_SER_DEV_SIGNATURE;
- UsbSerialDevice->SerialIo.Reset = SerialReset;
- UsbSerialDevice->SerialIo.SetControl = SetControlBits;
- UsbSerialDevice->SerialIo.SetAttributes = SetAttributes;
- UsbSerialDevice->SerialIo.GetControl = GetControlBits;
- UsbSerialDevice->SerialIo.Read = ReadSerialIo;
- UsbSerialDevice->SerialIo.Write = WriteSerialIo;
- //
- // Set the static Serial IO modes that will display when running
- // "sermode" within the UEFI shell.
- //
- UsbSerialDevice->SerialIo.Mode->Timeout = 0;
- UsbSerialDevice->SerialIo.Mode->BaudRate = 115200;
- UsbSerialDevice->SerialIo.Mode->DataBits = 8;
- UsbSerialDevice->SerialIo.Mode->Parity = 1;
- UsbSerialDevice->SerialIo.Mode->StopBits = 1;
- UsbSerialDevice->ParentDevicePath = ParentDevicePath;
- UsbSerialDevice->ControllerHandle = NULL;
- FlowControl = NULL;
- //
- // Allocate space for the receive buffer
- //
- UsbSerialDevice->DataBuffer = AllocateZeroPool (SW_FIFO_DEPTH);
- //
- // Initialize data buffer pointers.
- // Head==Tail = true means buffer is empty.
- //
- UsbSerialDevice->DataBufferHead = 0;
- UsbSerialDevice->DataBufferTail = 0;
- UsbSerialDevice->ControllerNameTable = NULL;
- AddUnicodeString2 (
- "eng",
- gUsbSerialComponentName.SupportedLanguages,
- &UsbSerialDevice->ControllerNameTable,
- L"FTDI USB Serial Adapter",
- TRUE
- );
- AddUnicodeString2 (
- "en",
- gUsbSerialComponentName2.SupportedLanguages,
- &UsbSerialDevice->ControllerNameTable,
- L"FTDI USB Serial Adapter",
- FALSE
- );
- Status = SetInitialStatus (UsbSerialDevice);
- ASSERT_EFI_ERROR (Status);
- //
- // Create a polling loop to check for input
- //
- gBS->CreateEvent (
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- UsbSerialDriverCheckInput,
- UsbSerialDevice,
- &(UsbSerialDevice->PollingLoop)
- );
- //
- // add code to set trigger time based on baud rate
- // setting to 0.5s for now
- //
- gBS->SetTimer (
- UsbSerialDevice->PollingLoop,
- TimerPeriodic,
- EFI_TIMER_PERIOD_MILLISECONDS (500)
- );
- //
- // Check if the remaining device path is null. If it is not null change the settings
- // of the device to match those on the device path
- //
- if (RemainingDevicePath != NULL) {
- CopyMem (
- &UsbSerialDevice->UartDevicePath,
- RemainingDevicePath,
- sizeof (UART_DEVICE_PATH)
- );
- FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath);
- if (IsUartFlowControlNode (FlowControl)) {
- UsbSerialDevice->FlowControlDevicePath.FlowControlMap = ReadUnaligned32 (&FlowControl->FlowControlMap);
- } else {
- FlowControl = NULL;
- }
- }
- //
- // Build the device path by appending the UART node to the parent device path
- //
- UsbSerialDevice->DevicePath = AppendDevicePathNode (
- ParentDevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->UartDevicePath
- );
- //
- // Continue building the device path by appending the flow control node
- //
- TempDevicePath = UsbSerialDevice->DevicePath;
- UsbSerialDevice->DevicePath = AppendDevicePathNode (
- TempDevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *) &UsbSerialDevice->FlowControlDevicePath
- );
- FreePool (TempDevicePath);
- if (UsbSerialDevice->DevicePath == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ErrorExit;
- }
- //
- // Install protocol interfaces for the device
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &UsbSerialDevice->ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- UsbSerialDevice->DevicePath,
- &gEfiSerialIoProtocolGuid,
- &UsbSerialDevice->SerialIo,
- NULL
- );
- if (EFI_ERROR (Status)){
- goto ErrorExit;
- }
- //
- // Open for child device
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- UsbSerialDevice->ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- UsbSerialDevice->Shutdown = FALSE;
- return EFI_SUCCESS;
- ErrorExit:
- //
- // Error handler
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- Controller,
- &gEfiSerialIoProtocolGuid,
- &UsbSerialDevice->SerialIo,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ErrorExit1;
- }
- FreePool (UsbSerialDevice->DataBuffer);
- FreePool (UsbSerialDevice);
- UsbSerialDevice = NULL;
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- ErrorExit1:
- return Status;
- }
- /**
- Stop the USB Serial device handled by this driver.
- @param This[in] The USB Serial driver binding protocol.
- @param Controller[in] The controller to release.
- @param NumberOfChildren[in] The number of handles in ChildHandleBuffer.
- @param ChildHandleBuffer[in] The array of child handle.
- @retval EFI_SUCCESS The device was stopped.
- @retval EFI_UNSUPPORTED Serial IO Protocol is not installed on
- Controller.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a
- device error.
- @retval Others Fail to uninstall protocols attached on the
- device.
- **/
- EFI_STATUS
- EFIAPI
- UsbSerialDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
- {
- EFI_STATUS Status;
- EFI_SERIAL_IO_PROTOCOL *SerialIo;
- EFI_USB_IO_PROTOCOL *UsbIo;
- USB_SER_DEV *UsbSerialDevice;
- UINTN Index;
- BOOLEAN AllChildrenStopped;
- Status = EFI_SUCCESS;
- UsbSerialDevice = NULL;
- if (NumberOfChildren == 0) {
- //
- // Close the driver
- //
- Status = gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- Status = gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- return Status;
- }
- AllChildrenStopped = TRUE;
- for (Index = 0; Index < NumberOfChildren ;Index++) {
- Status = gBS->OpenProtocol (
- ChildHandleBuffer[Index],
- &gEfiSerialIoProtocolGuid,
- (VOID **) &SerialIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (Status == EFI_SUCCESS) {//!EFI_ERROR (Status)) {
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (SerialIo);
- Status = gBS->CloseProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- This->DriverBindingHandle,
- ChildHandleBuffer[Index]
- );
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ChildHandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- UsbSerialDevice->DevicePath,
- &gEfiSerialIoProtocolGuid,
- &UsbSerialDevice->SerialIo,
- NULL
- );
- if (EFI_ERROR (Status)) {
- gBS->OpenProtocol (
- Controller,
- &gEfiUsbIoProtocolGuid,
- (VOID **) &UsbIo,
- This->DriverBindingHandle,
- ChildHandleBuffer[Index],
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- } else {
- if (UsbSerialDevice->DevicePath != NULL) {
- gBS->FreePool (UsbSerialDevice->DevicePath);
- }
- gBS->SetTimer (
- UsbSerialDevice->PollingLoop,
- TimerCancel,
- 0
- );
- gBS->CloseEvent (UsbSerialDevice->PollingLoop);
- UsbSerialDevice->Shutdown = TRUE;
- FreeUnicodeStringTable (UsbSerialDevice->ControllerNameTable);
- FreePool (UsbSerialDevice->DataBuffer);
- FreePool (UsbSerialDevice);
- }
- }
- if (EFI_ERROR (Status)) {
- AllChildrenStopped = FALSE;
- }
- }
- if (!AllChildrenStopped) {
- return EFI_DEVICE_ERROR;
- }
- return EFI_SUCCESS;
- }
- //
- // Serial IO Member Functions
- //
- /**
- Reset the serial device.
- @param This[in] Protocol instance pointer.
- @retval EFI_SUCCESS The device was reset.
- @retval EFI_DEVICE_ERROR The serial device could not be reset.
- **/
- EFI_STATUS
- EFIAPI
- SerialReset (
- IN EFI_SERIAL_IO_PROTOCOL *This
- )
- {
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
- Status = ResetInternal (UsbSerialDevice);
- if (EFI_ERROR (Status)){
- return EFI_DEVICE_ERROR;
- }
- return Status;
- }
- /**
- Set the control bits on a serial device.
- @param This[in] Protocol instance pointer.
- @param Control[in] Set the bits of Control that are settable.
- @retval EFI_SUCCESS The new control bits were set on the serial device.
- @retval EFI_UNSUPPORTED The serial device does not support this operation.
- @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
- **/
- EFI_STATUS
- EFIAPI
- SetControlBits (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN UINT32 Control
- )
- {
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
- CONTROL_BITS ControlBits;
-
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
-
- //
- // check for invalid control parameters
- //
- if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND |
- EFI_SERIAL_DATA_TERMINAL_READY |
- EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE |
- EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE))) != 0 ) {
- return EFI_UNSUPPORTED;
- }
- //
- // check the control parameters and set the correct setting for
- // the paramerts of ControlBits
- // both loopback enables are always set to FALSE
- //
- ControlBits.HardwareLoopBack = FALSE;
- ControlBits.SoftwareLoopBack = FALSE;
- //
- // check for hardware flow control
- //
- if ((Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
- ControlBits.HardwareFlowControl = TRUE;
- } else {
- ControlBits.HardwareFlowControl = FALSE;
- }
- //
- // check for DTR enabled
- //
- if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) {
- ControlBits.DtrState = TRUE;
- } else {
- ControlBits.DtrState = FALSE;
- }
- //
- // check for RTS enabled
- //
- if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) {
- ControlBits.RtsState = TRUE;
- } else {
- ControlBits.RtsState = FALSE;
- }
- //
- // set the control values with a call to SetControlBitsInternal()
- //
- Status = SetControlBitsInternal (UsbSerialDevice, &ControlBits);
- return Status;
- }
- /**
- calls SetAttributesInternal() to set the baud rate, receive FIFO depth,
- transmit/receive time out, parity, data buts, and stop bits on a serial
- device.
- @param This[in] Protocol instance pointer.
- @param BaudRate[in] The requested baud rate. A BaudRate value of 0
- will use the device's default interface speed.
- @param ReveiveFifoDepth[in] The requested depth of the FIFO on the receive
- side of the serial interface. A ReceiveFifoDepth
- value of 0 will use the device's default FIFO
- depth.
- @param Timeout[in] The requested time out for a single character in
- microseconds.This timeout applies to both the
- transmit and receive side of the interface. A
- Timeout value of 0 will use the device's default
- time out value.
- @param Parity[in] The type of parity to use on this serial device.
- A Parity value of DefaultParity will use the
- device's default parity value.
- @param DataBits[in] The number of data bits to use on the serial
- device. A DataBit vaule of 0 will use the
- device's default data bit setting.
- @param StopBits[in] The number of stop bits to use on this serial
- device. A StopBits value of DefaultStopBits will
- use the device's default number of stop bits.
- @retval EFI_SUCCESS The attributes were set
- @retval EFI_DEVICE_ERROR The attributes were not able to be
- **/
- EFI_STATUS
- EFIAPI
- SetAttributes (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN UINT64 BaudRate,
- IN UINT32 ReceiveFifoDepth,
- IN UINT32 Timeout,
- IN EFI_PARITY_TYPE Parity,
- IN UINT8 DataBits,
- IN EFI_STOP_BITS_TYPE StopBits
- )
- {
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
- Status = SetAttributesInternal (
- UsbSerialDevice,
- BaudRate,
- ReceiveFifoDepth,
- Timeout,
- Parity,
- DataBits,
- StopBits
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- return Status;
- }
- /**
- Retrieves the status of the control bits on a serial device.
- @param This[in] Protocol instance pointer.
- @param Control[out] A pointer to return the current Control signals
- from the serial device.
- @retval EFI_SUCCESS The control bits were read from the serial
- device.
- @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
- **/
- EFI_STATUS
- EFIAPI
- GetControlBits (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- OUT UINT32 *Control
- )
- {
- USB_SER_DEV *UsbSerialDevice;
- EFI_STATUS Status;
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
- *Control = 0;
- Status = GetControlBitsInternal (UsbSerialDevice, Control);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- return Status;
- }
- /**
- Reads data from a serial device.
- @param This[in] Protocol instance pointer.
- @param BufferSize[in, out] On input, the size of the Buffer. On output,
- the amount of data returned in Buffer.
- @param Buffer[out] The buffer to return the data into.
- @retval EFI_SUCCESS The data was read.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_TIMEOUT The data write was stopped due to a timeout.
- **/
- EFI_STATUS
- EFIAPI
- ReadSerialIo (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- OUT VOID *Buffer
- )
- {
- UINTN Index;
- UINTN RemainingCallerBufferSize;
- USB_SER_DEV *UsbSerialDevice;
- EFI_STATUS Status;
- if (*BufferSize == 0) {
- return EFI_SUCCESS;
- }
- if (Buffer == NULL) {
- return EFI_DEVICE_ERROR;
- }
- Status = EFI_SUCCESS;
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
- //
- // Clear out any data that we already have in our internal buffer
- //
- for (Index = 0; Index < *BufferSize; Index++) {
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- break;
- }
- //
- // Still have characters in the buffer to return
- //
- ((UINT8 *)Buffer)[Index] = UsbSerialDevice->DataBuffer[UsbSerialDevice->DataBufferHead];
- UsbSerialDevice->DataBufferHead = (UsbSerialDevice->DataBufferHead + 1) % SW_FIFO_DEPTH;
- }
- //
- // If we haven't filled the caller's buffer using data that we already had on
- // hand We need to generate an additional USB request to try and fill the
- // caller's buffer
- //
- if (Index != *BufferSize) {
- RemainingCallerBufferSize = *BufferSize - Index;
- Status = ReadDataFromUsb (
- UsbSerialDevice,
- &RemainingCallerBufferSize,
- (VOID *)(((CHAR8 *)Buffer) + Index)
- );
- if (!EFI_ERROR (Status)) {
- *BufferSize = RemainingCallerBufferSize + Index;
- } else {
- *BufferSize = Index;
- }
- }
- if (UsbSerialDevice->DataBufferHead == UsbSerialDevice->DataBufferTail) {
- //
- // Data buffer has no data, set the EFI_SERIAL_INPUT_BUFFER_EMPTY flag
- //
- UsbSerialDevice->ControlBits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
- } else {
- //
- // There is some leftover data, clear EFI_SERIAL_INPUT_BUFFER_EMPTY flag
- //
- UsbSerialDevice->ControlBits &= ~(EFI_SERIAL_INPUT_BUFFER_EMPTY);
- }
- return Status;
- }
- /**
- Writes data to a serial device.
- @param This[in] Protocol instance pointer.
- @param BufferSize[in, out] On input, the size of the Buffer. On output,
- the amount of data actually written.
- @param Buffer[in] The buffer of data to write
- @retval EFI_SUCCESS The data was written.
- @retval EFI_DEVICE_ERROR The device reported an error.
- @retval EFI_TIMEOUT The data write was stopped due to a timeout.
- **/
- EFI_STATUS
- EFIAPI
- WriteSerialIo (
- IN EFI_SERIAL_IO_PROTOCOL *This,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- )
- {
- EFI_STATUS Status;
- USB_SER_DEV *UsbSerialDevice;
- EFI_TPL Tpl;
- UsbSerialDevice = USB_SER_DEV_FROM_THIS (This);
- if (UsbSerialDevice->Shutdown) {
- return EFI_DEVICE_ERROR;
- }
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
- Status = UsbSerialDataTransfer (
- UsbSerialDevice,
- EfiUsbDataOut,
- Buffer,
- BufferSize,
- FTDI_TIMEOUT
- );
- gBS->RestoreTPL (Tpl);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_TIMEOUT){
- return Status;
- } else {
- return EFI_DEVICE_ERROR;
- }
- }
- return EFI_SUCCESS;
- }
|