Example #1
0
/*  Returns a bit mask describing which operations could be completed immediately.

    (POLLIN | POLLRDNORM)   A Unicode character is available to read
    (POLLIN)                A ScanCode is ready.
    (POLLOUT)               The device is ready for output - always set on stdout and stderr.

*/
static
short
EFIAPI
da_ConPoll(
  struct __filedes   *filp,
  short              events
  )
{
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *Proto;
  ConInstance                      *Stream;
  EFI_STATUS                        Status = RETURN_SUCCESS;
  short                             RdyMask = 0;

  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
  // Quick check to see if Stream looks reasonable
  if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
    EFIerrno = RETURN_INVALID_PARAMETER;
    return POLLNVAL;    // Looks like a bad filp pointer
  }
  if(Stream->InstanceNum == 0) {
    // Only input is supported for this device
    Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
    if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
      Status = Proto->ReadKeyStroke(Proto, &Stream->UnGetKey);
      if(Status == RETURN_SUCCESS) {
        RdyMask = POLLIN;
        if(Stream->UnGetKey.UnicodeChar != CHAR_NULL) {
          RdyMask |= POLLRDNORM;
        }
      }
      else {
        Stream->UnGetKey.ScanCode     = SCAN_NULL;
        Stream->UnGetKey.UnicodeChar  = CHAR_NULL;
      }
    }
  }
  else if(Stream->InstanceNum < NUM_SPECIAL) {  // Not 0, is it 1 or 2?
    // Only output is supported for this device
    RdyMask = POLLOUT;
  }
  else {
    RdyMask = POLLERR;    // Not one of the standard streams
  }
  EFIerrno = Status;

  return (RdyMask & (events | POLL_RETONLY));
}
Example #2
0
/** Read characters from the console input device.

    @param[in,out]  filp          Pointer to file descriptor for this file.
    @param[in,out]  offset        Ignored.
    @param[in]      BufferSize    Buffer size, in bytes.
    @param[out]     Buffer        Buffer in which to place the read characters.

    @return     Number of bytes actually placed into Buffer.

    @todo       Handle encodings other than ASCII-7 and UEFI.
**/
static
ssize_t
EFIAPI
da_ConRead(
  IN OUT  struct __filedes   *filp,
  IN OUT  off_t              *offset,         // Console ignores this
  IN      size_t              BufferSize,
     OUT  VOID               *Buffer
)
{
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *Proto;
  ConInstance                      *Stream;
  wchar_t                          *OutPtr;
  EFI_INPUT_KEY                     Key;
  UINTN                             NumChar;
  UINTN                             Edex;
  EFI_STATUS                        Status = RETURN_SUCCESS;
  UINTN                             i;
  char                              EchoBuff[MB_CUR_MAX + 1];
  int                               NumEcho;

  Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
  // Quick check to see if Stream looks reasonable
  if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
    EFIerrno = RETURN_INVALID_PARAMETER;
    return -1;    // Looks like a bad This pointer
  }
  if(Stream->InstanceNum != STDIN_FILENO) {
    // Read only valid for stdin
    EFIerrno = RETURN_UNSUPPORTED;
    return -1;
  }
  // It looks like things are OK for trying to read
  // We will accumulate *BufferSize characters or until we encounter
  // an "activation" character.  Currently any control character.
  Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
  OutPtr = ConReadBuf;
  NumChar = (BufferSize > MAX_INPUT)? MAX_INPUT : BufferSize;
  i = 0;
  do {
    if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
      Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
      if(Status != RETURN_SUCCESS) {
        break;
      }
      Status = Proto->ReadKeyStroke(Proto, &Key);
      if(Status != RETURN_SUCCESS) {
        break;
      }
    }
    else {
      Key.ScanCode          = Stream->UnGetKey.ScanCode;
      Key.UnicodeChar       = Stream->UnGetKey.UnicodeChar;
      Stream->UnGetKey.ScanCode     = SCAN_NULL;
      Stream->UnGetKey.UnicodeChar  = CHAR_NULL;
    }
    if(Key.ScanCode == SCAN_NULL) {
      NumEcho = 0;
      if(TtyCooked && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
        *OutPtr++ = CHAR_LINEFEED;
        NumEcho = wctomb(EchoBuff, CHAR_LINEFEED);
      }
      else {
        *OutPtr++ = Key.UnicodeChar;
        NumEcho = wctomb(EchoBuff, Key.UnicodeChar);
      }
      ++i;
      EchoBuff[NumEcho] = 0;  /* Terminate the Echo buffer */
      if(TtyEcho) {
        /* Echo the character just input */
        da_ConWrite(&gMD->fdarray[STDOUT_FILENO], NULL, 2, EchoBuff);
      }
    }
    if(iswcntrl(Key.UnicodeChar)) {    // If a control character, or a scan code
      break;
    }
  } while(i < NumChar);

  *OutPtr = L'\0';    // Terminate the input buffer

  /*  Convert the input buffer and place in Buffer.
      If the fully converted input buffer won't fit, write what will and
      leave the rest in ConReadBuf with ConReadLeft indicating how many
      unconverted characters remain in ConReadBuf.
  */
  NumEcho = (int)wcstombs(Buffer, ConReadBuf, BufferSize);   /* Re-use NumEcho to hold number of bytes in Buffer */
  /* More work needs to be done before locales other than C can be supported. */

  EFIerrno = Status;
  return (ssize_t)NumEcho;  // Will be 0 if we didn't get a key
}