openfirmware: Refactor console implementation following bootloader changes.

Confirmed working on sparc

Change-Id: I60bf82978ccf967e7e10611f6360cadccf22d15d
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4667
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Augustin Cavalier 2021-10-28 11:10:31 -04:00 committed by waddlesplash
parent 9aba9395e7
commit 7d41530f62
3 changed files with 76 additions and 97 deletions

View File

@ -65,7 +65,7 @@ Handle::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize)
}
off_t
off_t
Handle::Size() const
{
// ToDo: fix this!

View File

@ -9,9 +9,7 @@
#include <boot/vfs.h>
#ifdef __cplusplus
class Handle : public ConsoleNode {
class Handle : public Node {
public:
Handle(intptr_t handle, bool takeOwnership = true);
Handle();
@ -29,6 +27,4 @@ class Handle : public ConsoleNode {
bool fOwnHandle;
};
#endif /* __cplusplus */
#endif /* HANDLE_H */

View File

@ -18,59 +18,86 @@
#include "Handle.h"
class ConsoleHandle : public Handle {
class Console : public ConsoleNode {
public:
ConsoleHandle();
Console();
void SetHandles(intptr_t readHandle, intptr_t writeHandle, bool takeOwnership = true);
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
size_t bufferSize);
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
size_t bufferSize);
};
class InputConsoleHandle : public ConsoleHandle {
public:
InputConsoleHandle();
virtual void ClearScreen();
virtual int32 Width();
virtual int32 Height();
virtual void SetCursor(int32 x, int32 y);
virtual void SetCursorVisible(bool visible);
virtual void SetColors(int32 foreground, int32 background);
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
size_t bufferSize);
void PutChar(char c);
void PutChars(const char *buffer, int count);
void PutBackChar(char c);
void PutBackChars(const char *buffer, int count);
char GetChar();
private:
enum { BUFFER_SIZE = 32 };
Handle fReadHandle, fWriteHandle;
char fBuffer[BUFFER_SIZE];
enum { BUFFER_SIZE = 32 };
char fReadBuffer[BUFFER_SIZE];
int fStart;
int fCount;
};
static InputConsoleHandle sInput;
static ConsoleHandle sOutput;
extern ConsoleNode* gConsoleNode;
static Console sConsole;
FILE *stdin, *stdout, *stderr;
ConsoleHandle::ConsoleHandle()
Console::Console()
:
Handle()
ConsoleNode()
{
}
void
Console::SetHandles(intptr_t readHandle, intptr_t writeHandle, bool takeOwnership)
{
fReadHandle.SetHandle(readHandle, takeOwnership);
fWriteHandle.SetHandle(readHandle, takeOwnership);
}
ssize_t
ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer,
Console::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
size_t bufferSize)
{
// don't seek in character devices
return of_read(fHandle, buffer, bufferSize);
char *buffer = (char*)_buffer;
// copy buffered bytes first
int bytesTotal = 0;
while (bufferSize > 0 && fCount > 0) {
*buffer++ = GetChar();
bytesTotal++;
bufferSize--;
}
// read from console
if (bufferSize > 0) {
ssize_t bytesRead = fReadHandle.ReadAt(NULL, -1, buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
bytesTotal += bytesRead;
}
return bytesTotal;
}
ssize_t
ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
Console::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
size_t bufferSize)
{
const char *string = (const char *)buffer;
@ -96,7 +123,7 @@ ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
}
if (length > 0) {
of_write(fHandle, string, length);
fWriteHandle.WriteAt(NULL, -1, string, length);
string += length;
bufferSize -= length;
}
@ -104,7 +131,7 @@ ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
if (newLine) {
// this code replaces a single '\n' with '\r\n', so it
// bumps the string/bufferSize only a single character
of_write(fHandle, "\r\n", 2);
fWriteHandle.WriteAt(NULL, -1, "\r\n", 2);
string++;
bufferSize--;
}
@ -114,72 +141,34 @@ ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
}
// #pragma mark -
InputConsoleHandle::InputConsoleHandle()
:
ConsoleHandle(),
fStart(0),
fCount(0)
{
}
ssize_t
InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
size_t bufferSize)
{
char *buffer = (char*)_buffer;
// copy buffered bytes first
int bytesTotal = 0;
while (bufferSize > 0 && fCount > 0) {
*buffer++ = GetChar();
bytesTotal++;
bufferSize--;
}
// read from console
if (bufferSize > 0) {
ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
bytesTotal += bytesRead;
}
return bytesTotal;
}
void
InputConsoleHandle::PutChar(char c)
Console::PutBackChar(char c)
{
if (fCount >= BUFFER_SIZE)
return;
int pos = (fStart + fCount) % BUFFER_SIZE;
fBuffer[pos] = c;
fReadBuffer[pos] = c;
fCount++;
}
void
InputConsoleHandle::PutChars(const char *buffer, int count)
Console::PutBackChars(const char *buffer, int count)
{
for (int i = 0; i < count; i++)
PutChar(buffer[i]);
PutBackChar(buffer[i]);
}
char
InputConsoleHandle::GetChar()
Console::GetChar()
{
if (fCount == 0)
return 0;
fCount--;
char c = fBuffer[fStart];
char c = fReadBuffer[fStart];
fStart = (fStart + 1) % BUFFER_SIZE;
return c;
}
@ -199,12 +188,12 @@ console_init(void)
return B_ERROR;
}
sInput.SetHandle(input);
sOutput.SetHandle(output);
sConsole.SetHandles(input, output);
gConsoleNode = &sConsole;
// now that we're initialized, enable stdio functionality
stdin = (FILE *)&sInput;
stdout = stderr = (FILE *)&sOutput;
stdin = (FILE *)gConsoleNode;
stdout = stderr = (FILE *)gConsoleNode;
return B_OK;
}
@ -214,12 +203,12 @@ console_init(void)
void
console_clear_screen(void)
Console::ClearScreen()
{
#ifdef __sparc__
// Send both a clear screen (for serial terminal) and a vertical form
// feed for on-screen console
sOutput.Write("\014\033[2J", 5);
Write("\014\033[2J", 5);
#else
of_interpret("erase-screen", 0, 0);
#endif
@ -227,7 +216,7 @@ console_clear_screen(void)
int32
console_width(void)
Console::Width()
{
intptr_t columnCount;
#ifdef __sparc__
@ -241,7 +230,7 @@ console_width(void)
int32
console_height(void)
Console::Height()
{
intptr_t lineCount;
#ifdef __sparc__
@ -255,13 +244,13 @@ console_height(void)
void
console_set_cursor(int32 x, int32 y)
Console::SetCursor(int32 x, int32 y)
{
#ifdef __sparc__
char buffer[11];
int len = snprintf(buffer, sizeof(buffer),
"\033[%" B_PRId32 ";%" B_PRId32 "H", y, x);
sOutput.Write(buffer, len);
Write(buffer, len);
#else
// Note: We toggle the cursor temporarily to prevent a cursor artifact at
// at the old location.
@ -275,13 +264,7 @@ console_set_cursor(int32 x, int32 y)
void
console_show_cursor(void)
{
}
void
console_hide_cursor(void)
Console::SetCursorVisible(bool visible)
{
}
@ -317,14 +300,14 @@ translate_color(int32 color)
void
console_set_color(int32 foreground, int32 background)
Console::SetColors(int32 foreground, int32 background)
{
#ifdef __sparc__
// Sadly it seems we can only get inverse video, nothing else seems to work
if (background != 0)
sOutput.Write("\033[7m", 4);
Write("\033[7m", 4);
else
sOutput.Write("\033[0m", 4);
Write("\033[0m", 4);
#else
// Note: Toggling the cursor doesn't seem to help. We still get cursor
// artifacts.
@ -369,7 +352,7 @@ console_wait_for_key(void)
char buffer[3];
ssize_t bytesRead;
do {
bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
bytesRead = sConsole.ReadAt(NULL, 0, buffer, 3);
if (bytesRead < 0)
return 0;
} while (bytesRead == 0);
@ -383,7 +366,7 @@ console_wait_for_key(void)
// put back unread chars
if (bytesRead > 1)
sInput.PutChars(buffer + 1, bytesRead - 1);
sConsole.PutBackChars(buffer + 1, bytesRead - 1);
return buffer[0];
}
@ -393,7 +376,7 @@ int
console_check_for_key(void)
{
char buffer[3];
ssize_t bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
ssize_t bytesRead = sConsole.ReadAt(NULL, 0, buffer, 3);
if (bytesRead <= 0)
return 0;
@ -406,7 +389,7 @@ console_check_for_key(void)
// put back unread chars
if (bytesRead > 1)
sInput.PutChars(buffer + 1, bytesRead - 1);
sConsole.PutBackChars(buffer + 1, bytesRead - 1);
return buffer[0];
}