Home | History | Annotate | Download | only in InteractiveIO
      1 /** @file
      2   Utilities for Interactive I/O Functions.
      3 
      4   The functions assume that isatty() is TRUE at the time they are called.
      5 
      6   Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
      7   This program and the accompanying materials are licensed and made available
      8   under the terms and conditions of the BSD License which accompanies this
      9   distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php.
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 **/
     15 #include  <Uefi.h>
     16 #include  <Protocol/SimpleTextOut.h>
     17 
     18 #include  <LibConfig.h>
     19 
     20 #include  <assert.h>
     21 #include  <errno.h>
     22 #include  <sys/syslimits.h>
     23 #include  <sys/termios.h>
     24 #include  <Device/IIO.h>
     25 #include  <MainData.h>
     26 #include  "IIOutilities.h"
     27 
     28 /** Get the low-level UEFI protocol associated with an open file.
     29 
     30     @param[in]    fd    File descriptor for an open file.
     31     @param[out]   filp  NULL, or a pointer to where a pointer to the file's
     32                         file descriptor structure is to be stored.
     33 
     34     @return   Returns NULL if fd is not a valid file descriptor, otherwise
     35               a pointer to the file's associated UEFI protocol is returned.
     36 **/
     37 void *
     38 EFIAPI
     39 IIO_GetDeviceProto (
     40   int                 fd,
     41   struct __filedes  **filp
     42   )
     43 {
     44   void               *Proto;
     45   ConInstance        *Stream;
     46   struct __filedes   *pfil;
     47 
     48   Proto = NULL;
     49   if(ValidateFD( fd, VALID_OPEN)) {
     50     pfil = &gMD->fdarray[fd];
     51     Stream = BASE_CR(pfil->f_ops, ConInstance, Abstraction);
     52     Proto = (void *)Stream->Dev;
     53     if(filp != NULL) {
     54       *filp = pfil;
     55     }
     56   }
     57   return Proto;
     58 }
     59 
     60 /** Get a character either from the input buffer or from hardware.
     61 
     62     @param[in]    filp      Pointer to a file descriptor structure.
     63     @param[in]    First     Set to TRUE to identify the initial read.
     64 
     65     @return   Returns a character read from either the input buffer
     66               or from the open file (device) identified by filp.
     67               A return value of WEOF indicates an error has occurred.
     68 **/
     69 wint_t
     70 EFIAPI
     71 IIO_GetInChar (
     72   struct __filedes *filp,
     73   BOOLEAN           First
     74 )
     75 {
     76   cIIO             *This;
     77   cFIFO            *InBuf;
     78   size_t            Status;
     79   ssize_t           NumRead;
     80   wint_t            RetVal;
     81   wchar_t           InChar;
     82 
     83   static size_t     BufCnt;
     84 
     85   This      = filp->devdata;
     86   InBuf     = This->InBuf;
     87 
     88   NumRead = -1;
     89   InChar  =  0;
     90   if(First) {
     91     BufCnt = InBuf->Count(InBuf, AsElements);
     92   }
     93   if(BufCnt > 0) {
     94     Status = InBuf->Read(InBuf, &InChar, 1);
     95     if (Status > 0) {
     96       --BufCnt;
     97       NumRead = 1;
     98     }
     99   }
    100   else {
    101     NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar);
    102   }
    103   if(NumRead <= 0) {
    104     RetVal = WEOF;
    105   }
    106   else {
    107     RetVal = (wint_t)InChar;
    108   }
    109   return RetVal;
    110 }
    111 
    112 /** Get the current cursor position.
    113 
    114     @param[in]      fd      File descriptor for an open file.
    115     @param[out]     Column  Pointer to where the current cursor column is to be stored.
    116     @param[out]     Row     Pointer to where the current cursor row is to be stored.
    117 
    118     @retval   -1    fd is not an IIO output device.
    119     @retval    0    Cursor position retrieved, Cursor is Not Visible.
    120     @retval    1    Cursor position retrieved, Cursor is Visible.
    121 **/
    122 int
    123 EFIAPI
    124 IIO_GetCursorPosition (
    125   int       fd,
    126   UINT32   *Column,
    127   UINT32   *Row
    128   )
    129 {
    130   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *Proto;
    131   struct __filedes                   *pStdOut;
    132   int                                 RetVal;
    133 
    134   RetVal    = -1;
    135 
    136   Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
    137   if(Proto != NULL) {
    138     if(((pStdOut->f_iflags & _S_ITTY) != 0) &&    // file is a TTY
    139        ((pStdOut->Oflags & O_ACCMODE) != 0))      // and it is open for output
    140     {
    141       // fd is for a TTY or "Interactive IO" device
    142       *Column  = Proto->Mode->CursorColumn;
    143       *Row     = Proto->Mode->CursorRow;
    144       if(Proto->Mode->CursorVisible) {
    145         RetVal = 1;
    146       }
    147       else {
    148         RetVal = 0;
    149       }
    150     }
    151   }
    152   return RetVal;
    153 }
    154 
    155 /** Set the cursor position.
    156 
    157     @param[in]    filp    Pointer to the output device's file descriptor structure.
    158     @param[in]    StartXY Pointer to a cursor coordinate (XY) structure indicating
    159                           the desired coordinate to move the cursor to.
    160 
    161     @retval   -1    fd is not an IIO output device
    162     @retval    0    Cursor position set successfully.
    163 **/
    164 int
    165 EFIAPI
    166 IIO_SetCursorPosition (
    167   struct __filedes *filp,
    168   CURSOR_XY        *CursorXY
    169   )
    170 {
    171   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *Proto;
    172   cIIO                               *This;
    173   EFI_STATUS                          Status;
    174   int                                 RetVal;
    175 
    176   RetVal    = -1;
    177 
    178   This = filp->devdata;
    179   Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(filp->MyFD, NULL);
    180   if(Proto != NULL) {
    181     if(((filp->f_iflags & _S_ITTY) != 0) &&    // file is a TTY
    182        ((filp->Oflags & O_ACCMODE) != 0))      // and it is open for output
    183     {
    184       // fd is for a TTY or "Interactive IO" device
    185       Status = Proto->SetCursorPosition(Proto, CursorXY->Column, CursorXY->Row);
    186       if(Status == EFI_SUCCESS) {
    187         This->CurrentXY.Column  = CursorXY->Column;
    188         This->CurrentXY.Row     = CursorXY->Row;
    189         RetVal = 0;
    190       }
    191     }
    192   }
    193   return RetVal;
    194 }
    195 
    196 /** Get Output screen size and mode.
    197 
    198     @param[in]    fd    File descriptor of the output device.
    199     @param[out]   Col   Pointer to where to store the MAX Column, or NULL.
    200     @param[out]   Row   Pointer to where to store the MAX Row, or NULL.
    201 
    202     @retval   <0    An error occurred.  The reason is in errno and EFIerrno.
    203                       * EIO     UEFI QueryMode failed
    204                       * ENOTTY  fd does not refer to an interactive output device
    205     @retval   >=0   Current output mode
    206 **/
    207 int
    208 EFIAPI
    209 IIO_GetOutputSize (
    210   int       fd,
    211   UINTN    *Col,
    212   UINTN    *Row
    213 )
    214 {
    215   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *Proto;
    216   struct __filedes                   *pStdOut;
    217   EFI_STATUS                          Status;
    218   UINTN                               TempCol;
    219   UINTN                               TempRow;
    220   UINTN                               TempMode;
    221   int                                 RetVal;
    222 
    223   RetVal    = -1;
    224 
    225   Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
    226   if(Proto != NULL) {
    227     if(((pStdOut->f_iflags & _S_ITTY) != 0)   &&    // file is a TTY
    228         ((pStdOut->Oflags & O_ACCMODE) != 0))       // and it is open for output
    229     {
    230       // fd is for a TTY or "Interactive IO" device
    231       TempMode = Proto->Mode->Mode;
    232       Status = Proto->QueryMode(Proto, TempMode, &TempCol, &TempRow);
    233       if(EFI_ERROR(Status)) {
    234         EFIerrno  = Status;
    235         errno     = EIO;
    236       }
    237       else {
    238         *Col    = TempCol;
    239         *Row    = TempRow;
    240         RetVal  = (int)TempMode;
    241       }
    242     }
    243     else {
    244       errno = ENOTTY;
    245     }
    246   }
    247   return RetVal;
    248 }
    249 
    250 /** Calculate the number of character positions between two X/Y coordinate pairs.
    251 
    252     Using the current output device characteristics, calculate the number of
    253     characters between two coordinates.  It is assumed that EndXY points to
    254     an output location that occurs after StartXY.
    255 
    256     RowDelta is the computed difference between the ending and starting rows.
    257     If RowDelta < 0, then EndXY is NOT after StartXY, so assert.
    258 
    259     ColumnDelta is the computed number of character positions (columns) between
    260     the starting position and the ending position.  If ColumnDelta is < 0,
    261     then EndXY is NOT after StartXY, so assert.
    262 
    263     @param[in]      This      Pointer to the IIO instance to be examined.
    264     @param[in]      StartXY   Pointer to the starting coordinate pair.
    265     @param[in]      EndXY     Pointer to the ending coordinate pair.
    266 
    267     @return   Returns the difference between the starting and ending coordinates.
    268               The return value is positive if the coordinates contained in EndXY
    269               are larger than StartXY, otherwise the return value is negative.
    270 **/
    271 int
    272 EFIAPI
    273 IIO_CursorDelta (
    274   cIIO         *This,
    275   CURSOR_XY    *StartXY,
    276   CURSOR_XY    *EndXY
    277 )
    278 {
    279   int    ColumnDelta;
    280   int    RowDelta;
    281 
    282   RowDelta = (int)EndXY->Row - (int)StartXY->Row;
    283 
    284   assert(RowDelta >= 0);    // assert if EndXY is NOT after StartXY
    285 
    286   ColumnDelta = (int)((This->MaxColumn * RowDelta) + EndXY->Column);
    287   ColumnDelta -= (int)StartXY->Column;
    288 
    289   return ColumnDelta;
    290 }
    291