/** @file | |
Utilities for Interactive I/O Functions. | |
The functions assume that isatty() is TRUE at the time they are called. | |
Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials are licensed and made available | |
under the terms and conditions of the BSD License which accompanies this | |
distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php. | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include <Uefi.h> | |
#include <Protocol/SimpleTextOut.h> | |
#include <LibConfig.h> | |
#include <assert.h> | |
#include <errno.h> | |
#include <sys/syslimits.h> | |
#include <sys/termios.h> | |
#include <Device/IIO.h> | |
#include <MainData.h> | |
#include "IIOutilities.h" | |
/** Get the low-level UEFI protocol associated with an open file. | |
@param[in] fd File descriptor for an open file. | |
@param[out] filp NULL, or a pointer to where a pointer to the file's | |
file descriptor structure is to be stored. | |
@return Returns NULL if fd is not a valid file descriptor, otherwise | |
a pointer to the file's associated UEFI protocol is returned. | |
**/ | |
void * | |
EFIAPI | |
IIO_GetDeviceProto ( | |
int fd, | |
struct __filedes **filp | |
) | |
{ | |
void *Proto; | |
ConInstance *Stream; | |
struct __filedes *pfil; | |
Proto = NULL; | |
if(ValidateFD( fd, VALID_OPEN)) { | |
pfil = &gMD->fdarray[fd]; | |
Stream = BASE_CR(pfil->f_ops, ConInstance, Abstraction); | |
Proto = (void *)Stream->Dev; | |
if(filp != NULL) { | |
*filp = pfil; | |
} | |
} | |
return Proto; | |
} | |
/** Get a character either from the input buffer or from hardware. | |
@param[in] filp Pointer to a file descriptor structure. | |
@param[in] First Set to TRUE to identify the initial read. | |
@return Returns a character read from either the input buffer | |
or from the open file (device) identified by filp. | |
A return value of WEOF indicates an error has occurred. | |
**/ | |
wint_t | |
EFIAPI | |
IIO_GetInChar ( | |
struct __filedes *filp, | |
BOOLEAN First | |
) | |
{ | |
cIIO *This; | |
cFIFO *InBuf; | |
size_t Status; | |
ssize_t NumRead; | |
wint_t RetVal; | |
wchar_t InChar; | |
static size_t BufCnt; | |
This = filp->devdata; | |
InBuf = This->InBuf; | |
NumRead = -1; | |
InChar = 0; | |
if(First) { | |
BufCnt = InBuf->Count(InBuf, AsElements); | |
} | |
if(BufCnt > 0) { | |
Status = InBuf->Read(InBuf, &InChar, 1); | |
if (Status > 0) { | |
--BufCnt; | |
NumRead = 1; | |
} | |
} | |
else { | |
NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar); | |
} | |
if(NumRead <= 0) { | |
RetVal = WEOF; | |
} | |
else { | |
RetVal = (wint_t)InChar; | |
} | |
return RetVal; | |
} | |
/** Get the current cursor position. | |
@param[in] fd File descriptor for an open file. | |
@param[out] Column Pointer to where the current cursor column is to be stored. | |
@param[out] Row Pointer to where the current cursor row is to be stored. | |
@retval -1 fd is not an IIO output device. | |
@retval 0 Cursor position retrieved, Cursor is Not Visible. | |
@retval 1 Cursor position retrieved, Cursor is Visible. | |
**/ | |
int | |
EFIAPI | |
IIO_GetCursorPosition ( | |
int fd, | |
UINT32 *Column, | |
UINT32 *Row | |
) | |
{ | |
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto; | |
struct __filedes *pStdOut; | |
int RetVal; | |
RetVal = -1; | |
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut); | |
if(Proto != NULL) { | |
if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY | |
((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output | |
{ | |
// fd is for a TTY or "Interactive IO" device | |
*Column = Proto->Mode->CursorColumn; | |
*Row = Proto->Mode->CursorRow; | |
if(Proto->Mode->CursorVisible) { | |
RetVal = 1; | |
} | |
else { | |
RetVal = 0; | |
} | |
} | |
} | |
return RetVal; | |
} | |
/** Set the cursor position. | |
@param[in] filp Pointer to the output device's file descriptor structure. | |
@param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating | |
the desired coordinate to move the cursor to. | |
@retval -1 fd is not an IIO output device | |
@retval 0 Cursor position set successfully. | |
**/ | |
int | |
EFIAPI | |
IIO_SetCursorPosition ( | |
struct __filedes *filp, | |
CURSOR_XY *CursorXY | |
) | |
{ | |
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto; | |
cIIO *This; | |
EFI_STATUS Status; | |
int RetVal; | |
RetVal = -1; | |
This = filp->devdata; | |
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(filp->MyFD, NULL); | |
if(Proto != NULL) { | |
if(((filp->f_iflags & _S_ITTY) != 0) && // file is a TTY | |
((filp->Oflags & O_ACCMODE) != 0)) // and it is open for output | |
{ | |
// fd is for a TTY or "Interactive IO" device | |
Status = Proto->SetCursorPosition(Proto, CursorXY->Column, CursorXY->Row); | |
if(Status == EFI_SUCCESS) { | |
This->CurrentXY.Column = CursorXY->Column; | |
This->CurrentXY.Row = CursorXY->Row; | |
RetVal = 0; | |
} | |
} | |
} | |
return RetVal; | |
} | |
/** Get Output screen size and mode. | |
@param[in] fd File descriptor of the output device. | |
@param[out] Col Pointer to where to store the MAX Column, or NULL. | |
@param[out] Row Pointer to where to store the MAX Row, or NULL. | |
@retval <0 An error occurred. The reason is in errno and EFIerrno. | |
* EIO UEFI QueryMode failed | |
* ENOTTY fd does not refer to an interactive output device | |
@retval >=0 Current output mode | |
**/ | |
int | |
EFIAPI | |
IIO_GetOutputSize ( | |
int fd, | |
UINTN *Col, | |
UINTN *Row | |
) | |
{ | |
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto; | |
struct __filedes *pStdOut; | |
EFI_STATUS Status; | |
UINTN TempCol; | |
UINTN TempRow; | |
UINTN TempMode; | |
int RetVal; | |
RetVal = -1; | |
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut); | |
if(Proto != NULL) { | |
if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY | |
((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output | |
{ | |
// fd is for a TTY or "Interactive IO" device | |
TempMode = Proto->Mode->Mode; | |
Status = Proto->QueryMode(Proto, TempMode, &TempCol, &TempRow); | |
if(EFI_ERROR(Status)) { | |
EFIerrno = Status; | |
errno = EIO; | |
} | |
else { | |
*Col = TempCol; | |
*Row = TempRow; | |
RetVal = (int)TempMode; | |
} | |
} | |
else { | |
errno = ENOTTY; | |
} | |
} | |
return RetVal; | |
} | |
/** Calculate the number of character positions between two X/Y coordinate pairs. | |
Using the current output device characteristics, calculate the number of | |
characters between two coordinates. It is assumed that EndXY points to | |
an output location that occurs after StartXY. | |
RowDelta is the computed difference between the ending and starting rows. | |
If RowDelta < 0, then EndXY is NOT after StartXY, so assert. | |
ColumnDelta is the computed number of character positions (columns) between | |
the starting position and the ending position. If ColumnDelta is < 0, | |
then EndXY is NOT after StartXY, so assert. | |
@param[in] This Pointer to the IIO instance to be examined. | |
@param[in] StartXY Pointer to the starting coordinate pair. | |
@param[in] EndXY Pointer to the ending coordinate pair. | |
@return Returns the difference between the starting and ending coordinates. | |
The return value is positive if the coordinates contained in EndXY | |
are larger than StartXY, otherwise the return value is negative. | |
**/ | |
int | |
EFIAPI | |
IIO_CursorDelta ( | |
cIIO *This, | |
CURSOR_XY *StartXY, | |
CURSOR_XY *EndXY | |
) | |
{ | |
int ColumnDelta; | |
int RowDelta; | |
RowDelta = (int)EndXY->Row - (int)StartXY->Row; | |
assert(RowDelta >= 0); // assert if EndXY is NOT after StartXY | |
ColumnDelta = (int)((This->MaxColumn * RowDelta) + EndXY->Column); | |
ColumnDelta -= (int)StartXY->Column; | |
return ColumnDelta; | |
} |