/** Remove one pre-fetched key out of the FIFO buffer. @param TerminalDevice Terminal driver private structure. @param Output The key will be removed. @retval TRUE If insert successfully. @retval FLASE If FIFO buffer is empty before remove operation. **/ BOOLEAN EfiKeyFiFoRemoveOneKey ( TERMINAL_DEV *TerminalDevice, EFI_INPUT_KEY *Output ) { UINT8 Head; Head = TerminalDevice->EfiKeyFiFo->Head; ASSERT (Head < FIFO_MAX_NUMBER + 1); if (IsEfiKeyFiFoEmpty (TerminalDevice)) { // // FIFO is empty // Output->ScanCode = SCAN_NULL; Output->UnicodeChar = 0; return FALSE; } *Output = TerminalDevice->EfiKeyFiFo->Data[Head]; TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1)); return TRUE; }
/** Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event Signal the event if there is key available @param Event Indicates the event that invoke this function. @param Context Indicates the calling context. **/ VOID EFIAPI TerminalConInWaitForKey ( IN EFI_EVENT Event, IN VOID *Context ) { // // Someone is waiting on the keystroke event, if there's // a key pending, signal the event // if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) { gBS->SignalEvent (Event); } }
/** Check for a pending key in the Efi Key FIFO or Serial device buffer. @param This Indicates the calling context. @retval EFI_SUCCESS There is key pending. @retval EFI_NOT_READY There is no key pending. @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device. **/ EFI_STATUS TerminalConInCheckForKey ( IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This ) { EFI_STATUS Status; TERMINAL_DEV *TerminalDevice; UINT32 Control; UINT8 Input; EFI_SERIAL_IO_MODE *Mode; EFI_SERIAL_IO_PROTOCOL *SerialIo; UINTN SerialInTimeOut; TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); SerialIo = TerminalDevice->SerialIo; if (SerialIo == NULL) { return EFI_DEVICE_ERROR; } // // if current timeout value for serial device is not identical with // the value saved in TERMINAL_DEV structure, then recalculate the // timeout value again and set serial attribute according to this value. // Mode = SerialIo->Mode; if (Mode->Timeout != TerminalDevice->SerialInTimeOut) { SerialInTimeOut = 0; if (Mode->BaudRate != 0) { // // According to BAUD rate to calculate the timeout value. // SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate; } Status = SerialIo->SetAttributes ( SerialIo, Mode->BaudRate, Mode->ReceiveFifoDepth, (UINT32) SerialInTimeOut, (EFI_PARITY_TYPE) (Mode->Parity), (UINT8) Mode->DataBits, (EFI_STOP_BITS_TYPE) (Mode->StopBits) ); if (EFI_ERROR (Status)) { TerminalDevice->SerialInTimeOut = 0; } else { TerminalDevice->SerialInTimeOut = SerialInTimeOut; } } // // Check whether serial buffer is empty. // Status = SerialIo->GetControl (SerialIo, &Control); if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) { // // Translate all the raw data in RawFIFO into EFI Key, // according to different terminal type supported. // TranslateRawDataToEfiKey (TerminalDevice); // // if there is pre-fetched Efi Key in EfiKeyFIFO buffer, // return directly. // if (!IsEfiKeyFiFoEmpty (TerminalDevice)) { return EFI_SUCCESS; } else { return EFI_NOT_READY; } } // // Fetch all the keys in the serial buffer, // and insert the byte stream into RawFIFO. // do { Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input); if (EFI_ERROR (Status)) { if (Status == EFI_DEVICE_ERROR) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR), TerminalDevice->DevicePath ); } break; } RawFiFoInsertOneKey (TerminalDevice, Input); } while (TRUE); // // Translate all the raw data in RawFIFO into EFI Key, // according to different terminal type supported. // TranslateRawDataToEfiKey (TerminalDevice); if (IsEfiKeyFiFoEmpty (TerminalDevice)) { return EFI_NOT_READY; } return EFI_SUCCESS; }