/* 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)); }
/** 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 }