Jaben, Erik, whomever: Please review the attached files.

AppPkg: New application for exercising interactive Console I/O in several modes.

ConsoleIO.inf,
ConsoleIO.h,      Private declarations.
ConsoleIO.c,      Main part of the application.
FkPrint.c,             Utility functions for printing a buffer and including 
names of non-printing keys, if any.
FunKey.c,            Utility data and functions for printing the names of 
non-printing keys
TermInfo.c,        Dump the termios structure for stdin in a human readable 
format
AppPkg.dsc        Adds one line to describe the ConsoleIO application

NOTE! The file ConsoleIO.inf is attached as ConsoleIO.inf.txt in order to make 
it past corporate mail filters.

If everything is working properly, this application isn't very interesting.  
But, it can be useful for investigating when things go awry.

Thanks,
Daryl McDaniel

/** @file
    Copyright (c) 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.

    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  <stdio.h>
#include  <sys/termios.h>
#include  "ConsoleIO.h"

/// Names of input flags from termios.c_iflag
const FlagEnt InFlags[NumInFlags] = {
  { "INLCR",    INLCR },
  { "IGNCR",    IGNCR },
  { "ICRNL",    ICRNL },
  { "IGNSPEC",  IGNSPEC }
};

/// Names of control flags from termios.c_cflag
const FlagEnt CtrlFlags[] = {
  { "null",    0 }
};

/// Names of output flags from termios.c_oflag
const FlagEnt OutFlags[NumOutFlags] = {
  { "OPOST",  OPOST },
  { "ONLCR",  ONLCR },
  { "OXTABS", OXTABS },
  { "ONOEOT", ONOEOT },
  { "OCRNL",  OCRNL },
  { "ONOCR",  ONOCR },
  { "ONLRET", ONLRET },
  { "OCTRL",  OCTRL }
};

/// Names of local flags from termios.c_lflag
const FlagEnt LocalFlags[NumLocalFlags] = {
  { "ECHO",     ECHO },
  { "ECHOE",    ECHOE },
  { "ECHOK",    ECHOK },
  { "ECHONL",   ECHONL },
  { "ISIG",     ISIG },
  { "ICANON",   ICANON },
  { "IEXTEN",   IEXTEN },
  { "TOSTOP",   TOSTOP },
  { "PENDIN",   PENDIN },
  { "NOFLSH",   NOFLSH },
  { "FLUSHO",   FLUSHO }
};

/// Names of elements of the c_cc array from termios.c_cc
const FlagEnt CcNames[NCCS] = {
  { "VTABLEN",    0 },
  { "VEOF",       1 },
  { "VEOL",       1 },
  { "VERASE",     1 },
  { "VKILL",      1 },
  { "VINTR",      1 },
  { "VQUIT",      1 },
  { "VMIN",       0 },
  { "VTIME",      0 },
  { "VWERASE",    1 },
  { "VREPRINT",   1 },
  { "VLNEXT",     1 },
  { "VDISCARD",   1 }
};

/** Print the flags given the Flag value and a pointer to an array of possible 
names.

  @param[in]    Header    Pointer to a string to print before the flag values
  @param[in]    FlagVal   The bitmapped flags to be identified
  @param[in]    Table     Pointer to the array of potential flag names
  @param[in]    NumFlags  Number of names defined in Table
**/
void
ListFlags (
  const char      * const Header,
  const tcflag_t          FlagVal,
  const FlagEnt   * const Table,
  const UINT32            NumFlags
  )
{
  UINT32 i;

  printf("%8s: [0x%04X] ", Header, FlagVal);
  for (i = 0; i < NumFlags; ++i) {
    if ((FlagVal & Table[i].FlagValue) != 0) {
      printf(" %s", Table[i].FlagName);
    }
  }
  puts("");
}

/** Print a description of each member of the c_cc array.

  @param[in]  c_cc    Pointer to the c_cc array to dump.
  @param[in]  Table   Pointer to the table of names for the c_cc members.
**/
void
PrintCCC (
  cc_t            * const c_cc,
  const FlagEnt   * const Table
  )
{
  int           i;
  unsigned char c;

  puts("Control Character array (c_cc):");
  for (i = 0; i < NCCS; ++i) {
    c = c_cc[i];
    printf("  %9s: [0x%02X]", Table[i].FlagName, c);
    if (Table[i].FlagValue == 1) {
      if (c < 0x7f) {
        if (c < ' ') {
          c += '@';
          printf("  '^%c'", c);
        }
        else {
          fputs("  '?'", stdout);
        }
      }
      else {
        fputs("  Disabled", stdout);
      }
    }
    puts("");
  }
}

/** Print a description of each element of the termios structure.

  @param[in]  TermInfo  Pointer to the termios structure to dump.
**/
void
DumpTermios (
  struct termios *TermInfo
  )
{
  puts("termios structure for stdin:");
  /* input speed    */
  printf("Input Speed: %d\n", TermInfo->c_ispeed);
  /* output speed   */
  printf("Output Speed: %d\n", TermInfo->c_ospeed);
  /* input flags    */
  ListFlags ("Input", TermInfo->c_iflag, InFlags, NumInFlags);
  /* output flags   */
  ListFlags ("Output", TermInfo->c_oflag, OutFlags, NumOutFlags);
  /* control flags  */
  ListFlags ("Control", TermInfo->c_cflag, CtrlFlags, NumCtrlFlags);
  /* local flags    */
  ListFlags ("Local", TermInfo->c_lflag, LocalFlags, NumLocalFlags);
  /* control chars  */
  PrintCCC (&TermInfo->c_cc[0], CcNames);
  puts("");
}
/** @file
    Exercise Console I/O functions in several modes.

    Type END in order to exit.

    Copyright (c) 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.

    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  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <sys/EfiSysCall.h>
#include  <sys/termios.h>
#include  "ConsoleIO.h"

const char  Identify[] = "\
Console I/O Test.  Echos input in several modes.\n\
Type END to exit.\n";

const char  HelpText[] = "\
  Syntax:  conio [Options]\n\
  Options are:\n\
    -h    Display this Help message.\n\
    -?    Display this Help message.\n\
    -s    Stop ignoring function and other special keys.\n\
    -t    Dump the termios structure for stdin.\n\
    -v    Verbose output.\n\
";

/** Remove the trailing newline from a buffered line.

  Finds the first newline in a buffer and replaces it with a NUL character.
  The buffer is assumed to be MBCS and not UCS2.

  @param[in,out]    Buff    Pointer to the buffer containing the line to modify.
**/
VOID
StripNL( char *Buff)
{
  Buff = strchr(Buff, '\n');
  if(Buff != NULL) {
    *Buff = 0;
  }
}

/** Get and process command line options.

  @param[in]  Argc    Number of arguments pointed to by Argv.
  @param[in]  Argv    Array of pointers to arguments.

  @return   A bitmapped set of flags identifying the recognized options.
**/
UINT32
GetOptions(
  int Argc,
  char  **Argv
  )
{
  char   *Arg;
  UINT32  Options;
  int     i;

  Options = 0;

  for (i = 1; i < Argc; ++i) {
    Arg = Argv[i];

    if (Arg[0] != '-') {
      continue;
    }
    switch (Arg[1]) {
      case 'd': // Set VEOF to EOT (^D)
        Options |= FLAG_D;
        break;

      case 'h':
      case '?': // Help
        Options |= FLAG_H;
        break;

      case 's': // Read Scan Codes
        Options |= FLAG_S;
        break;

      case 't': // Dump the termios structure
        Options |= FLAG_T;
        break;

      case 'v': // Verbose
        Options |= FLAG_V;
        break;

      case 'z': // Set VEOF to SUB (^Z)
        Options |= FLAG_Z;
        break;

      default:
        break;
    }
  }
  return Options;
}

/** Console I/O exerciser.

  @param[in]  Argc    Number of argument tokens pointed to by Argv.
  @param[in]  Argv    Array of Argc pointers to command line tokens.

  @retval  0         The application exited normally.
  @retval  Non-Zero  An error occurred.
**/
int
main (
  IN int Argc,
  IN char **Argv
  )
{
  char           *fret;
  char           *inbuff;
  UINT32          Options;
  struct termios  TermConf;

  puts (Identify);

  // Process command-line Options ############################################

  Options = GetOptions (Argc, Argv);

  if (Options & FLAG_H) {
    puts (HelpText);
    return 0;
  }

  if (tcgetattr (STDIN_FILENO, &TermConf) != 0) {
    perror ("ERROR retrieving terminal attributes");
    return EXIT_FAILURE;
  }

  if ((Options & FLAG_D) != 0) {
    // Set VEOF to ^D (EOT)
    TermConf.c_cc[VEOF] = CHAR_EOT;
  }

  if ((Options & FLAG_S) != 0) {
    // Clear the IGNSPEC flag
    TermConf.c_iflag &= ~IGNSPEC;
  }

  if ((Options & FLAG_Z) != 0) {
    // Set VEOF to ^Z (SUB)
    TermConf.c_cc[VEOF] = CHAR_SUB;
  }

  if (Options != 0) {
    if (tcsetattr (STDIN_FILENO, TCSANOW, &TermConf) != 0) {
      perror ("ERROR setting terminal attributes");
      return EXIT_FAILURE;
    }
  }

  if (Options & FLAG_T) {
    DumpTermios (&TermConf);  // Dump the termios structure
  }

  // Actual work part of the application #####################################

  inbuff = malloc(512);
  if (inbuff == NULL) {
    puts("ERROR: Unable to malloc input buffer.");
    return -1;
  }

  do {
    fputs("Type  something: ", stdout);
    fret = fgets(inbuff, 100, stdin);

    if (fret == NULL) {
      perror("ERROR!  fgets() failed");
      break;
    }
    else {
      // Strip trailing line end.
      StripNL(inbuff);
      printf("fgets  returned \"%s\"\n", fret);
      FKprint("buffer contains", inbuff);
      putchar('\n');
    }
  } while(strcmp(inbuff, "END") != 0);

  free (inbuff);
  return 0;
}
/** @file
    Private declarations for the ConsoleIO test application.

    Copyright (c) 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.

    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
**/
#ifndef   CONSOLE_IO_H_
#define   CONSOLE_IO_H_

#define   NumNames    46    ///< Number of named special non-printing characters

/// Command Line Flags
/// @{
#define FLAG_A    0x00000001
#define FLAG_B    0x00000002
#define FLAG_C    0x00000004
#define FLAG_D    0x00000008
#define FLAG_E    0x00000010
#define FLAG_F    0x00000020
#define FLAG_G    0x00000040
#define FLAG_H    0x00000080    ///< Help
#define FLAG_I    0x00000100
#define FLAG_J    0x00000200
#define FLAG_K    0x00000400
#define FLAG_L    0x00000800
#define FLAG_M    0x00001000
#define FLAG_N    0x00002000
#define FLAG_O    0x00004000
#define FLAG_P    0x00008000
#define FLAG_Q    0x00010000
#define FLAG_R    0x00020000
#define FLAG_S    0x00040000    ///< Accept Special characters
#define FLAG_T    0x00080000    ///< Dump the termios structure for stdin
#define FLAG_U    0x00100000
#define FLAG_V    0x00200000    ///< Verbose
#define FLAG_W    0x00400000
#define FLAG_X    0x00800000
#define FLAG_Y    0x01000000
#define FLAG_Z    0x02000000
/// @}

/// Number of named flags in each of the flag name tables.
/// @{
#define NumInFlags      4
#define NumOutFlags     8
#define NumCtrlFlags    0
#define NumLocalFlags   11
/// @}

/// An array of pointers to the MBCS names of special non-printing characters.
extern const char * const FunNames[46];

/// Each entry in the flag name arrays is of this type
typedef struct FlagEnt {
  char   *FlagName;
  UINT32  FlagValue;
} FlagEnt;

/** Print the name of a key associated with ScanCode.

  @param[in]  ScanCode    Scan code associated with the key to print the name 
of.
**/
VOID
PrintFunKey (
  int   ScanCode
);

/** Print a buffer one character at a time, translating special characters as 
needed.

  The buffer will be printed after the message pointed to by Msg.  If buffer 
contains
  a non-printing character, such as a function key or arrow, a special tag will 
be
  printed identifying the character.  e.g.: <F1>, <Pg Up>, <Up>, ^G, ^I, ...

  The input buffer contains MBCS characters which are converted into Wide 
characters
  before processing.

  Example:
    Buff = "AbCdEfG";
    FKprint ("Buffer contents", Buff)
  will produce:
    Buffer contents "AbCdEfG"

  @param[in]  Msg     Message to prefix to Buffer contents
  @param[in]  Buff    Buffer to be displayed.
**/
void FKprint (
  const char * const Fmt,
  const char * const Buff
);

/** Print a description of each element of the termios structure.

  @param[in]  TermInfo  Pointer to the termios structure to dump.
**/
void DumpTermios (struct termios *TermStruc);

#endif    // CONSOLE_IO_H_
## @file
#   An application to test Console I/O functionality in several modes.
#
#  Copyright (c) 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.
#
#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
##

[Defines]
  INF_VERSION                    = 0x00010006
  BASE_NAME                      = ConsoleIO
  FILE_GUID                      = 8D559BE2-E6BA-462E-A104-A3818E984F1A
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 0.1
  ENTRY_POINT                    = ShellCEntryLib

#
#  VALID_ARCHITECTURES           = IA32 X64
#

[Sources]
  ConsoleIO.c
  FunKey.c
  FkPrint.c
  TermInfo.c

[Packages]
  StdLib/StdLib.dec
  MdePkg/MdePkg.dec
  ShellPkg/ShellPkg.dec

[LibraryClasses]
  LibC
  LibStdio
  LibString
  LibWchar
/** @file
    Print a buffer one character at a time, translating special characters as 
needed.

    Copyright (c) 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.

    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  <stdio.h>
#include  <stdlib.h>
#include  <wchar.h>
#include  <sys/types.h>
#include  <sys/termios.h>
#include  "ConsoleIO.h"

/** Print a buffer one character at a time, translating special characters as 
needed.

  The buffer will be printed after the message pointed to by Msg.  If buffer 
contains
  a non-printing character, such as a function key or arrow, a special tag will 
be
  printed identifying the character.  e.g.: <F1>, <Pg Up>, <Up>, ^G, ^I, ...

  The input buffer contains MBCS characters which are converted into Wide 
characters
  before processing.

  Example:
    Buff = "AbCdEfG";
    FKprint ("Buffer contents", Buff)
  will produce:
    Buffer contents "AbCdEfG"

  @param[in]  Msg     Message to prefix to Buffer contents
  @param[in]  Buff    Buffer to be displayed.
**/
void
FKprint (
  const char * const Msg,
  const char * const Buff
  )
{
  wchar_t  *WideBuff;
  wchar_t  *pWork;
  ssize_t    Val;
  wchar_t   CurChar;

  WideBuff = malloc(2048);
  if (WideBuff != NULL) {
    Val = (ssize_t)mbstowcs (WideBuff, Buff, 1024);
    if (Val < 0) {
      puts("ERROR: Invalid character encountered in buffer.");
    }
    else {
      fputs (Msg, stdout);
      fputs (" \"", stdout);
      // Val contains the number of characters in WideBuff
      pWork = WideBuff;
      for ( ; Val > 0; --Val) {
        CurChar = *pWork++;
        if((CurChar < TtyFunKeyMin) || (CurChar > TtyFunKeyMax)) {
          // Regular character, just print it.
          putwchar (CurChar);
        }
        else {
          // Function key or special character
          PrintFunKey (CurChar);
        }
      }
      fputs ("\"\n", stdout);
    }
    free(WideBuff);
  }
  else {
    puts("ERROR: Unable to malloc memory.");
  }
}
/** @file
    Defines an array of strings associated with each special/function key.
    Index 0 corresponds to TtyUpArrow with each increasing index going downward
    to TtyKeyEject.

    Also defines a function to get the name of a key given its scan code and a
    function to print the key's name.

    Copyright (c) 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.

    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  <stdio.h>
#include  <sys/termios.h>
#include  "ConsoleIO.h"

/// An array of pointers to the MBCS names of special non-printing characters.
const char * const FunNames[NumNames] = {
  { "Unknown" },    //TtyFunKeyMax  = 0xF900    63744 = 0
  { "Up" },         //TtyUpArrow    = 0xF8FF,   63743 = 1
  { "Down" },       //TtyDownArrow,             63742 = 2
  { "Right" },      //TtyRightArrow,            63741 = 3
  { "Left" },       //TtyLeftArrow,             63740 = 4
  { "Home" },       //TtyHome,                  63739 = 5
  { "End" },        //TtyEnd,                   63738 = 6
  { "Insert" },     //TtyInsert,                63737 = 7
  { "Delete" },     //TtyDelete,                63736 = 8
  { "Pg Up" },      //TtyPageUp,                63735 = 9
  { "Pg Down" },    //TtyPageDown,              63734 = 10
  { "F1" },         //TtyF1,                    63733 = 11
  { "F2" },         //TtyF2,                    63732 = 12
  { "F3" },         //TtyF3,                    63731 = 13
  { "F4" },         //TtyF4,                    63730 = 14
  { "F5" },         //TtyF5,                    63729 = 15
  { "F6" },         //TtyF6,                    63728 = 16
  { "F7" },         //TtyF7,                    63727 = 17
  { "F8" },         //TtyF8,                    63726 = 18
  { "F9" },         //TtyF9,                    63725 = 19
  { "F10" },        //TtyF10,                   63724 = 20
  { "F11" },        //TtyF11,                   63723 = 21
  { "F12" },        //TtyF12,                   63722 = 22
  { "ESC" },        //TtyEscape     = 0xF8E9,   63721 = 23

  { "F13" },        //TtyF13        = 0xF898,   63640 = 104  = 24    (80)
  { "F14" },        //TtyF14,                   63639 = 105  = 25
  { "F15" },        //TtyF15,                   63638 = 106  = 26
  { "F16" },        //TtyF16,                   63637 = 107  = 27
  { "F17" },        //TtyF17,                   63636 = 108  = 28
  { "F18" },        //TtyF18,                   63635 = 109  = 29
  { "F19" },        //TtyF19,                   63634 = 110  = 30
  { "F20" },        //TtyF20,                   63633 = 111  = 31
  { "F21" },        //TtyF21,                   63632 = 112  = 32
  { "F22" },        //TtyF22,                   63631 = 113  = 33
  { "F23" },        //TtyF23,                   63630 = 114  = 34
  { "F24" },        //TtyF24        = 0xF88D,   63629 = 115  = 35

  { "Mute" },       //TtyMute       = 0xF881,   63617 = 127  = 36    (91) (11)
  { "Vol Up" },     //TtyVolumeUp,              63616 = 128  = 37
  { "Vol Down" },   //TtyVolumeDown = 0xF87F,   63615 = 129  = 38

  { "Brighten" },   //TtyBrightnessUp = 0xF800, 63488 = 256  = 39    (217) (126)
  { "Dim" },        //TtyBrightnessDown,        63487 = 257  = 40
  { "Susp" },       //TtySuspend,               63486 = 258  = 41
  { "Hiber" },      //TtyHibernate,             63485 = 259  = 42
  { "Display" },    //TtyToggleDisplay,         63484 = 260  = 43
  { "Recovery" },   //TtyRecovery,              63483 = 261  = 44
  { "Eject" }       //TtyKeyEject   = 0xF7FA,   63482 = 262  = 45
};

/** Given the Scan Code of a special key, retrieve its name.
  ScanCodes that are within undefined ranges are given the name "Unknown", while
  ScanCodes that are outside the range of special keys are named "ERROR".

  @param[in]  ScanCode    Key to get the name of.

  @return     A pointer to the name of the key associated with ScanCode.
**/
const char *
FunKeyName (
  int   ScanCode
  )
{
  const char *Name;
  int         NameDex;

  NameDex = -1;

  if (ScanCode >= TtyFunKeyMin) {
    NameDex = TtyFunKeyMax - ScanCode;
    if (NameDex > 23) {
      NameDex -= 80;
      if (NameDex < 24) {
        NameDex = 0;
      }
    }
    if (NameDex > 35) {
      NameDex -= 11;
      if (NameDex < 36) {
        NameDex = 0;
      }
    }
    if (NameDex > 38) {
      NameDex -= 126;
      if (NameDex < 39) {
        NameDex = 0;
      }
    }
  }
  if ((NameDex < 0) || (NameDex >= NumNames)) {
    Name = "ERROR";
  }
  else {
    Name = FunNames[NameDex];
  }
  return Name;
}

/** Print the name of a key associated with ScanCode.

  @param[in]  ScanCode    Scan code associated with the key to print the name 
of.
**/
VOID
PrintFunKey (
  int   ScanCode
  )
{
  const char   *Name;

  Name = FunKeyName (ScanCode);
  printf("<%s>", Name);
}

Attachment: AppPkg.dsc
Description: AppPkg.dsc

------------------------------------------------------------------------------
Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server
from Actuate! Instantly Supercharge Your Business Reports and Dashboards
with Interactivity, Sharing, Native Excel Exports, App Integration & more
Get technology previously reserved for billion-dollar corporations, FREE
http://pubads.g.doubleclick.net/gampad/clk?id=157005751&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to